Commit 79d2008b authored by smolnar's avatar smolnar
Browse files

Backed out 2 changesets (bug 1689245) for causing failures in CompositorWidget. CLOSED TREE

Backed out changeset 60ad4f4b141d (bug 1689245)
Backed out changeset 778ecad5812e (bug 1689245)
parent d3a109a0
Loading
Loading
Loading
Loading
+22 −19
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ bool RenderCompositorSWGL::BeginFrame() {
  // Set up a temporary region representing the entire window surface in case a
  // dirty region is not supplied.
  ClearMappedBuffer();
  mDirtyRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
  mRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
  wr_swgl_make_current(mContext);
  return true;
}
@@ -60,10 +60,11 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
  // Request a new draw target to use from the widget...
  MOZ_ASSERT(!mDT);
  layers::BufferMode bufferMode = layers::BufferMode::BUFFERED;
  mDT = mWidget->StartRemoteDrawingInRegion(mDirtyRegion, &bufferMode);
  mDT = mWidget->StartRemoteDrawingInRegion(mRegion, &bufferMode);
  if (!mDT) {
    return false;
  }
  mWidget->ClearBeforePaint(mDT, mRegion);
  // Attempt to lock the underlying buffer directly from the draw target.
  // Verify that the size at least matches what the widget claims and that
  // the format is BGRA8 as SWGL requires.
@@ -80,7 +81,7 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
    mDT->ReleaseBits(data);
    data = nullptr;
  }
  LayoutDeviceIntRect bounds = mDirtyRegion.GetBounds();
  LayoutDeviceIntRect bounds = mRegion.GetBounds();
  // If locking succeeded above, just use that.
  if (data) {
    mMappedData = data;
@@ -105,7 +106,7 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
    gfx::DataSourceSurface::MappedSurface map = {nullptr, 0};
    if (!mSurface || !mSurface->Map(gfx::DataSourceSurface::READ_WRITE, &map)) {
      // We failed mapping the data surface, so need to cancel the frame.
      mWidget->EndRemoteDrawingInRegion(mDT, mDirtyRegion);
      mWidget->EndRemoteDrawingInRegion(mDT, mRegion);
      ClearMappedBuffer();
      return false;
    }
@@ -123,13 +124,15 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
                                      rect.size.width, rect.size.height));
  }

  LayoutDeviceIntRegion clear = mWidget->GetTransparentRegion();
  clear.AndWith(mDirtyRegion);
  clear.SubOut(opaque);
  RefPtr<DrawTarget> dt = gfx::Factory::CreateDrawTargetForData(
      BackendType::SKIA, mMappedData, bounds.Size().ToUnknownSize(),
      mMappedStride, SurfaceFormat::B8G8R8A8, false);

  LayoutDeviceIntRegion clear;
  clear.Sub(mRegion, opaque);
  for (auto iter = clear.RectIter(); !iter.Done(); iter.Next()) {
    const auto& rect = iter.Get();
    wr_swgl_clear_color_rect(mContext, 0, rect.x, rect.y, rect.width,
                             rect.height, 0, 0, 0, 0);
    dt->ClearRect(
        IntRectToRect((iter.Get() - bounds.TopLeft()).ToUnknownRect()));
  }

  return true;
@@ -142,19 +145,19 @@ void RenderCompositorSWGL::StartCompositing(
    // Cancel any existing buffers that might accidentally be left from updates
    CommitMappedBuffer(false);
    // Reset the region to the widget bounds
    mDirtyRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
    mRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
  }
  if (aNumDirtyRects) {
    // Install the dirty rects into the bounds of the existing region
    auto bounds = mDirtyRegion.GetBounds();
    mDirtyRegion.SetEmpty();
    auto bounds = mRegion.GetBounds();
    mRegion.SetEmpty();
    for (size_t i = 0; i < aNumDirtyRects; i++) {
      const auto& rect = aDirtyRects[i];
      mDirtyRegion.OrWith(LayoutDeviceIntRect(
          rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
      mRegion.OrWith(LayoutDeviceIntRect(rect.origin.x, rect.origin.y,
                                         rect.size.width, rect.size.height));
    }
    // Ensure the region lies within the widget bounds
    mDirtyRegion.AndWith(bounds);
    mRegion.AndWith(bounds);
  }
  // Now that the dirty rects have been supplied and the composition region
  // is known, allocate and install a framebuffer encompassing the composition
@@ -186,12 +189,12 @@ void RenderCompositorSWGL::CommitMappedBuffer(bool aDirty) {
      // that is offset from the origin to the actual bounds of the dirty
      // region. The destination DT may also be an offset partial region, but we
      // must check to see if its size matches the region bounds to verify this.
      LayoutDeviceIntRect bounds = mDirtyRegion.GetBounds();
      LayoutDeviceIntRect bounds = mRegion.GetBounds();
      gfx::IntPoint srcOffset = bounds.TopLeft().ToUnknownPoint();
      gfx::IntPoint dstOffset = mDT->GetSize() == bounds.Size().ToUnknownSize()
                                    ? srcOffset
                                    : gfx::IntPoint(0, 0);
      for (auto iter = mDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
      for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
        gfx::IntRect dirtyRect = iter.Get().ToUnknownRect();
        mDT->CopySurface(mSurface, dirtyRect - srcOffset,
                         dirtyRect.TopLeft() - dstOffset);
@@ -202,7 +205,7 @@ void RenderCompositorSWGL::CommitMappedBuffer(bool aDirty) {
    mDT->ReleaseBits(mMappedData);
  }
  // Done with the DT. Hand it back to the widget and clear out any trace of it.
  mWidget->EndRemoteDrawingInRegion(mDT, mDirtyRegion);
  mWidget->EndRemoteDrawingInRegion(mDT, mRegion);
  ClearMappedBuffer();
}

+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ class RenderCompositorSWGL : public RenderCompositor {
 private:
  void* mContext = nullptr;
  RefPtr<gfx::DrawTarget> mDT;
  LayoutDeviceIntRegion mDirtyRegion;
  LayoutDeviceIntRegion mRegion;
  RefPtr<gfx::DataSourceSurface> mSurface;
  uint8_t* mMappedData = nullptr;
  int32_t mMappedStride = 0;
+6 −18
Original line number Diff line number Diff line
@@ -91,22 +91,6 @@ pub extern "C" fn wr_swgl_set_texture_buffer(
    );
}

#[no_mangle]
pub extern "C" fn wr_swgl_clear_color_rect(
    ctx: *mut c_void,
    fbo: u32,
    x: i32,
    y: i32,
    width: i32,
    height: i32,
    r: f32,
    g: f32,
    b: f32,
    a: f32,
) {
    swgl::Context::from(ctx).clear_color_rect(fbo, x, y, width, height, r, g, b, a);
}

/// Descriptor for a locked surface that will be directly composited by SWGL.
#[repr(C)]
struct WrSWGLCompositeSurfaceInfo {
@@ -1636,7 +1620,11 @@ impl Compositor for SwCompositor {
    /// frame will not have overlap dependencies assigned and so must instead
    /// be added to the late_surfaces queue to be processed at the end of the
    /// frame.
    fn start_compositing(&mut self, dirty_rects: &[DeviceIntRect], _opaque_rects: &[DeviceIntRect]) {
    fn start_compositing(
        &mut self,
        dirty_rects: &[DeviceIntRect],
        _opaque_rects: &[DeviceIntRect],
    ) {
        // Opaque rects are currently only computed here, not by WR itself, so we
        // ignore the passed parameter and forward our own version onto the native
        // compositor.
+52 −196
Original line number Diff line number Diff line
@@ -600,7 +600,7 @@ struct Texture {
  uint32_t* cleared_rows = nullptr;

  void init_depth_runs(uint16_t z);
  void fill_depth_runs(uint16_t z, const IntRect& scissor);
  void fill_depth_runs(uint16_t z);

  void enable_delayed_clear(uint32_t val) {
    delay_clear = height;
@@ -904,7 +904,7 @@ struct Context {
  bool scissortest = false;
  IntRect scissor = {0, 0, 0, 0};

  GLfloat clearcolor[4] = {0, 0, 0, 0};
  uint32_t clearcolor = 0;
  GLdouble cleardepth = 1;

  int unpack_row_length = 0;
@@ -1290,15 +1290,10 @@ void Disable(GLenum cap) {
GLenum GetError() { return GL_NO_ERROR; }

static const char* const extensions[] = {
    "GL_ARB_blend_func_extended",
    "GL_ARB_clear_texture",
    "GL_ARB_copy_image",
    "GL_ARB_draw_instanced",
    "GL_ARB_explicit_attrib_location",
    "GL_ARB_instanced_arrays",
    "GL_ARB_invalidate_subdata",
    "GL_ARB_texture_storage",
    "GL_EXT_timer_query",
    "GL_ARB_blend_func_extended", "GL_ARB_copy_image",
    "GL_ARB_draw_instanced",      "GL_ARB_explicit_attrib_location",
    "GL_ARB_instanced_arrays",    "GL_ARB_invalidate_subdata",
    "GL_ARB_texture_storage",     "GL_EXT_timer_query",
    "GL_APPLE_rgb_422",
};

@@ -1489,10 +1484,8 @@ void SetScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
}

void ClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
  ctx->clearcolor[0] = r;
  ctx->clearcolor[1] = g;
  ctx->clearcolor[2] = b;
  ctx->clearcolor[3] = a;
  I32 c = round_pixel((Float){b, g, r, a});
  ctx->clearcolor = bit_cast<uint32_t>(CONVERT(c, U8));
}

void ClearDepth(GLdouble depth) { ctx->cleardepth = depth; }
@@ -2378,6 +2371,14 @@ static void clear_buffer(Texture& t, T value, int layer, IntRect bb,
  }
}

template <typename T>
static inline void clear_buffer(Texture& t, T value, int layer = 0) {
  IntRect bb = ctx->apply_scissor(t);
  if (bb.width() > 0) {
    clear_buffer<T>(t, value, layer, bb);
  }
}

template <typename T>
static inline void force_clear_row(Texture& t, int y, int skip_start = 0,
                                   int skip_end = 0) {
@@ -2465,35 +2466,30 @@ static void prepare_texture(Texture& t, const IntRect* skip) {
  }
}

static inline bool clear_requires_scissor(Texture& t) {
  return ctx->scissortest && !ctx->scissor.contains(t.offset_bounds());
}

// Setup a clear on a texture. This may either force an immediate clear or
// potentially punt to a delayed clear, if applicable.
template <typename T>
static void request_clear(Texture& t, int layer, T value,
                          const IntRect& scissor) {
static void request_clear(Texture& t, int layer, T value) {
  // If the clear would require a scissor, force clear anything outside
  // the scissor, and then immediately clear anything inside the scissor.
  if (!scissor.contains(t.offset_bounds())) {
    IntRect skip = scissor - t.offset;
  if (clear_requires_scissor(t)) {
    IntRect skip = ctx->scissor - t.offset;
    force_clear<T>(t, &skip);
    clear_buffer<T>(t, value, layer, skip.intersection(t.bounds()));
    clear_buffer<T>(t, value, layer);
  } else if (t.depth > 1) {
    // Delayed clear is not supported on texture arrays.
    t.disable_delayed_clear();
    clear_buffer<T>(t, value, layer, t.bounds());
    clear_buffer<T>(t, value, layer);
  } else {
    // Do delayed clear for 2D texture without scissor.
    t.enable_delayed_clear(value);
  }
}

template <typename T>
static inline void request_clear(Texture& t, int layer, T value) {
  // If scissoring is enabled, use the scissor rect. Otherwise, just scissor to
  // the entire texture bounds.
  request_clear(t, layer, value,
                ctx->scissortest ? ctx->scissor : t.offset_bounds());
}

// Initialize a depth texture by setting the first run in each row to encompass
// the entire row.
void Texture::init_depth_runs(uint16_t depth) {
@@ -2513,10 +2509,10 @@ static ALWAYS_INLINE void fill_depth_run(DepthRun* dst, size_t n,
}

// Fills a scissored region of a depth texture with a given depth.
void Texture::fill_depth_runs(uint16_t depth, const IntRect& scissor) {
void Texture::fill_depth_runs(uint16_t depth) {
  if (!buf) return;
  assert(cleared());
  IntRect bb = bounds().intersection(scissor - offset);
  IntRect bb = ctx->apply_scissor(*this);
  DepthRun* runs = (DepthRun*)sample_ptr(0, bb.y0);
  for (int rows = bb.height(); rows > 0; rows--) {
    if (bb.width() >= width) {
@@ -2591,180 +2587,40 @@ GLenum CheckFramebufferStatus(GLenum target) {
  return GL_FRAMEBUFFER_COMPLETE;
}

void ClearTexSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset,
                      GLint zoffset, GLsizei width, GLsizei height,
                      GLsizei depth, GLenum format, GLenum type,
                      const void* data) {
  if (level != 0) {
    assert(false);
    return;
  }
  Texture& t = ctx->textures[texture];
void Clear(GLbitfield mask) {
  Framebuffer& fb = *get_framebuffer(GL_DRAW_FRAMEBUFFER);
  if ((mask & GL_COLOR_BUFFER_BIT) && fb.color_attachment) {
    Texture& t = ctx->textures[fb.color_attachment];
    assert(!t.locked);
  if (zoffset < 0) {
    depth += zoffset;
    zoffset = 0;
  }
  if (zoffset + depth > max(t.depth, 1)) {
    depth = max(t.depth, 1) - zoffset;
  }
  if (width <= 0 || height <= 0 || depth <= 0) {
    return;
  }
  IntRect scissor = {xoffset, yoffset, xoffset + width, yoffset + height};
  if (t.internal_format == GL_DEPTH_COMPONENT16) {
    uint16_t value = 0xFFFF;
    switch (format) {
      case GL_DEPTH_COMPONENT:
        switch (type) {
          case GL_DOUBLE:
            value = uint16_t(*(const GLdouble*)data * 0xFFFF);
            break;
          case GL_FLOAT:
            value = uint16_t(*(const GLfloat*)data * 0xFFFF);
            break;
          case GL_UNSIGNED_SHORT:
            value = uint16_t(*(const GLushort*)data);
            break;
          default:
    if (t.internal_format == GL_RGBA8) {
      uint32_t color = ctx->clearcolor;
      request_clear<uint32_t>(t, fb.layer, color);
    } else if (t.internal_format == GL_R8) {
      uint8_t color = uint8_t((ctx->clearcolor >> 16) & 0xFF);
      request_clear<uint8_t>(t, fb.layer, color);
    } else if (t.internal_format == GL_RG8) {
      uint16_t color = uint16_t((ctx->clearcolor & 0xFF00) |
                                ((ctx->clearcolor >> 16) & 0xFF));
      request_clear<uint16_t>(t, fb.layer, color);
    } else {
      assert(false);
            break;
    }
        break;
      default:
        assert(false);
        break;
  }
    assert(zoffset == 0 && depth == 1);
    if (t.cleared() && !scissor.contains(t.offset_bounds())) {
  if ((mask & GL_DEPTH_BUFFER_BIT) && fb.depth_attachment) {
    Texture& t = ctx->textures[fb.depth_attachment];
    assert(t.internal_format == GL_DEPTH_COMPONENT16);
    uint16_t depth = uint16_t(0xFFFF * ctx->cleardepth);
    if (t.cleared() && clear_requires_scissor(t)) {
      // If we need to scissor the clear and the depth buffer was already
      // initialized, then just fill runs for that scissor area.
      t.fill_depth_runs(value, scissor);
      t.fill_depth_runs(depth);
    } else {
      // Otherwise, the buffer is either uninitialized or the clear would
      // encompass the entire buffer. If uninitialized, we can safely fill
      // the entire buffer with any value and thus ignore any scissoring.
      t.init_depth_runs(value);
    }
    return;
  }

  uint32_t color = 0xFF000000;
  switch (type) {
    case GL_FLOAT: {
      const GLfloat* f = (const GLfloat*)data;
      Float v = {0.0f, 0.0f, 0.0f, 1.0f};
      switch (format) {
        case GL_RGBA:
          v.w = f[3];  // alpha
          FALLTHROUGH;
        case GL_RGB:
          v.z = f[2];  // blue
          FALLTHROUGH;
        case GL_RG:
          v.y = f[1];  // green
          FALLTHROUGH;
        case GL_RED:
          v.x = f[0];  // red
          break;
        default:
          assert(false);
          break;
      }
      color = bit_cast<uint32_t>(CONVERT(round_pixel(v), U8));
      break;
    }
    case GL_UNSIGNED_BYTE: {
      const GLubyte* b = (const GLubyte*)data;
      switch (format) {
        case GL_RGBA:
          color = (color & ~0xFF000000) | (uint32_t(b[3]) << 24);  // alpha
          FALLTHROUGH;
        case GL_RGB:
          color = (color & ~0x00FF0000) | (uint32_t(b[2]) << 16);  // blue
          FALLTHROUGH;
        case GL_RG:
          color = (color & ~0x0000FF00) | (uint32_t(b[1]) << 8);  // green
          FALLTHROUGH;
        case GL_RED:
          color = (color & ~0x000000FF) | uint32_t(b[0]);  // red
          break;
        default:
          assert(false);
          break;
      }
      break;
    }
    default:
      assert(false);
      break;
  }

  for (int layer = zoffset; layer < zoffset + depth; layer++) {
    switch (t.internal_format) {
      case GL_RGBA8:
        // Clear color needs to swizzle to BGRA.
        request_clear<uint32_t>(t, layer,
                                (color & 0xFF00FF00) |
                                    ((color << 16) & 0xFF0000) |
                                    ((color >> 16) & 0xFF),
                                scissor);
        break;
      case GL_R8:
        request_clear<uint8_t>(t, layer, uint8_t(color & 0xFF), scissor);
        break;
      case GL_RG8:
        request_clear<uint16_t>(t, layer, uint16_t(color & 0xFFFF), scissor);
        break;
      default:
        assert(false);
        break;
    }
  }
}

void ClearTexImage(GLuint texture, GLint level, GLenum format, GLenum type,
                   const void* data) {
  Texture& t = ctx->textures[texture];
  IntRect scissor = t.offset_bounds();
  ClearTexSubImage(texture, level, scissor.x0, scissor.y0, 0, scissor.width(),
                   scissor.height(), max(t.depth, 1), format, type, data);
}

void Clear(GLbitfield mask) {
  Framebuffer& fb = *get_framebuffer(GL_DRAW_FRAMEBUFFER);
  if ((mask & GL_COLOR_BUFFER_BIT) && fb.color_attachment) {
    Texture& t = ctx->textures[fb.color_attachment];
    IntRect scissor = ctx->scissortest
                          ? ctx->scissor.intersection(t.offset_bounds())
                          : t.offset_bounds();
    ClearTexSubImage(fb.color_attachment, 0, scissor.x0, scissor.y0, fb.layer,
                     scissor.width(), scissor.height(), 1, GL_RGBA, GL_FLOAT,
                     ctx->clearcolor);
  }
  if ((mask & GL_DEPTH_BUFFER_BIT) && fb.depth_attachment) {
    Texture& t = ctx->textures[fb.depth_attachment];
    IntRect scissor = ctx->scissortest
                          ? ctx->scissor.intersection(t.offset_bounds())
                          : t.offset_bounds();
    ClearTexSubImage(fb.depth_attachment, 0, scissor.x0, scissor.y0, 0,
                     scissor.width(), scissor.height(), 1, GL_DEPTH_COMPONENT,
                     GL_DOUBLE, &ctx->cleardepth);
      t.init_depth_runs(depth);
    }
  }

void ClearColorRect(GLuint fbo, GLint xoffset, GLint yoffset, GLsizei width,
                    GLsizei height, GLfloat r, GLfloat g, GLfloat b,
                    GLfloat a) {
  GLfloat color[] = {r, g, b, a};
  Framebuffer& fb = ctx->framebuffers[fbo];
  Texture& t = ctx->textures[fb.color_attachment];
  IntRect scissor =
      IntRect{xoffset, yoffset, xoffset + width, yoffset + height}.intersection(
          t.offset_bounds());
  ClearTexSubImage(fb.color_attachment, 0, scissor.x0, scissor.y0, fb.layer,
                   scissor.width(), scissor.height(), 1, GL_RGBA, GL_FLOAT,
                   color);
}

void InvalidateFramebuffer(GLenum target, GLsizei num_attachments,
+0 −1
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ typedef intptr_t GLintptr;
#define GL_INT 0x1404
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_DOUBLE 0x1408

#define GL_RED 0x1903
#define GL_GREEN 0x1904
Loading