Attachment #514156: GL fix for bug #635373

View | Details | Raw Unified | Return to bug 635373
Collapse All | Expand All

(-)a/gfx/layers/ThebesLayerBuffer.cpp (-11 / +15 lines)
Line     Link Here 
 Lines 175-262   WrapRotationAxis(PRInt32* aRotationPoint Link Here 
175
    *aRotationPoint += aSize;
175
    *aRotationPoint += aSize;
176
  } else if (*aRotationPoint >= aSize) {
176
  } else if (*aRotationPoint >= aSize) {
177
    *aRotationPoint -= aSize;
177
    *aRotationPoint -= aSize;
178
  }
178
  }
179
}
179
}
180
180
181
ThebesLayerBuffer::PaintState
181
ThebesLayerBuffer::PaintState
182
ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
182
ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
183
                              const nsIntRegion& aNeededRegion,
183
                              float aXResolution, float aYResolution)
184
                              float aXResolution, float aYResolution)
184
{
185
{
185
  PaintState result;
186
  PaintState result;
186
187
187
  result.mRegionToDraw.Sub(aLayer->GetVisibleRegion(), aLayer->GetValidRegion());
188
  result.mRegionToDraw.Sub(aNeededRegion, aLayer->GetValidRegion());
188
189
189
  float curXRes = aLayer->GetXResolution();
190
  float curXRes = aLayer->GetXResolution();
190
  float curYRes = aLayer->GetYResolution();
191
  float curYRes = aLayer->GetYResolution();
191
  if (mBuffer &&
192
  if (mBuffer &&
192
      (aContentType != mBuffer->GetContentType() ||
193
      (aContentType != mBuffer->GetContentType() ||
193
       aXResolution != curXRes || aYResolution != curYRes)) {
194
       aXResolution != curXRes || aYResolution != curYRes)) {
194
    // We're effectively clearing the valid region, so we need to draw
195
    // We're effectively clearing the valid region, so we need to draw
195
    // the entire visible region now.
196
    // the entire needed region now.
196
    //
197
    //
197
    // XXX/cjones: a possibly worthwhile optimization to keep in mind
198
    // XXX/cjones: a possibly worthwhile optimization to keep in mind
198
    // is to re-use buffers when the resolution and visible region
199
    // is to re-use buffers when the resolution and visible region
199
    // have changed in such a way that the buffer size stays the same.
200
    // have changed in such a way that the buffer size stays the same.
200
    // It might make even more sense to allocate buffers from a
201
    // It might make even more sense to allocate buffers from a
201
    // recyclable pool, so that we could keep this logic simple and
202
    // recyclable pool, so that we could keep this logic simple and
202
    // still get back the same buffer.
203
    // still get back the same buffer.
203
    result.mRegionToDraw = aLayer->GetVisibleRegion();
204
    result.mRegionToDraw = aNeededRegion;
204
    result.mRegionToInvalidate = aLayer->GetValidRegion();
205
    result.mRegionToInvalidate = aLayer->GetValidRegion();
205
    Clear();
206
    Clear();
206
  }
207
  }
207
208
208
  if (result.mRegionToDraw.IsEmpty())
209
  if (result.mRegionToDraw.IsEmpty())
209
    return result;
210
    return result;
210
  nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
211
  nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
211
212
212
  nsIntRect visibleBounds = aLayer->GetVisibleRegion().GetBounds();
213
  nsIntRect neededBounds = aNeededRegion.GetBounds();
213
  nsIntSize destBufferDims = ScaledSize(visibleBounds.Size(),
214
  nsIntSize destBufferDims = ScaledSize(neededBounds.Size(),
214
                                        aXResolution, aYResolution);
215
                                        aXResolution, aYResolution);
215
  nsRefPtr<gfxASurface> destBuffer;
216
  nsRefPtr<gfxASurface> destBuffer;
216
  nsIntRect destBufferRect;
217
  nsIntRect destBufferRect;
217
  PRBool bufferDimsChanged = PR_FALSE;
218
  PRBool bufferDimsChanged = PR_FALSE;
218
219
219
  if (BufferSizeOkFor(destBufferDims)) {
220
  if (BufferSizeOkFor(destBufferDims)) {
220
    NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
221
    NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
221
                 "resolution changes must Clear()!");
222
                 "resolution changes must Clear()!");
222
223
223
    // The current buffer is big enough to hold the visible area.
224
    // The current buffer is big enough to hold the needed area.
224
    if (mBufferRect.Contains(visibleBounds)) {
225
    if (mBufferRect.Contains(neededBounds)) {
225
      // We don't need to adjust mBufferRect.
226
      // We don't need to adjust mBufferRect.
226
      destBufferRect = mBufferRect;
227
      destBufferRect = mBufferRect;
227
    } else {
228
    } else {
228
      // The buffer's big enough but doesn't contain everything that's
229
      // The buffer's big enough but doesn't contain everything that's
229
      // going to be visible. We'll move it.
230
      // going to be visible. We'll move it.
230
      destBufferRect = nsIntRect(visibleBounds.TopLeft(), mBufferRect.Size());
231
      destBufferRect = nsIntRect(neededBounds.TopLeft(), mBufferRect.Size());
231
    }
232
    }
232
    nsIntRect keepArea;
233
    nsIntRect keepArea;
233
    if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
234
    if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
234
      // Set mBufferRotation so that the pixels currently in mBuffer
235
      // Set mBufferRotation so that the pixels currently in mBuffer
235
      // will still be rendered in the right place when mBufferRect
236
      // will still be rendered in the right place when mBufferRect
236
      // changes to destBufferRect.
237
      // changes to destBufferRect.
237
      nsIntPoint newRotation = mBufferRotation +
238
      nsIntPoint newRotation = mBufferRotation +
238
        (destBufferRect.TopLeft() - mBufferRect.TopLeft());
239
        (destBufferRect.TopLeft() - mBufferRect.TopLeft());
239
      WrapRotationAxis(&newRotation.x, mBufferRect.width);
240
      WrapRotationAxis(&newRotation.x, mBufferRect.width);
240
      WrapRotationAxis(&newRotation.y, mBufferRect.height);
241
      WrapRotationAxis(&newRotation.y, mBufferRect.height);
241
      NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
242
      NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
242
                   "newRotation out of bounds");
243
                   "newRotation out of bounds");
243
      PRInt32 xBoundary = destBufferRect.XMost() - newRotation.x;
244
      PRInt32 xBoundary = destBufferRect.XMost() - newRotation.x;
244
      PRInt32 yBoundary = destBufferRect.YMost() - newRotation.y;
245
      PRInt32 yBoundary = destBufferRect.YMost() - newRotation.y;
245
      if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) ||
246
      if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) ||
246
          (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost())) {
247
          (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) ||
248
          (!mEnableRotationOptimization && newRotation != nsIntPoint(0,0))) {
247
        // The stuff we need to redraw will wrap around an edge of the
249
        // The stuff we need to redraw will wrap around an edge of the
248
        // buffer, so we will need to do a self-copy
250
        // buffer, so we will need to do a self-copy
249
        if (mBuffer->SupportsSelfCopy() && mBufferRotation == nsIntPoint(0,0)) {
251
        if (mBuffer->SupportsSelfCopy() && mBufferRotation == nsIntPoint(0,0)) {
250
          destBuffer = mBuffer;
252
          destBuffer = mBuffer;
251
        } else {
253
        } else {
252
          // We can't do a real self-copy because the buffer is rotated.
254
          // We can't do a real self-copy because the buffer is rotated.
253
          // So allocate a new buffer for the destination.
255
          // So allocate a new buffer for the destination.
254
          destBufferRect = visibleBounds;
256
          destBufferRect = neededBounds;
255
          destBufferDims = ScaledSize(destBufferRect.Size(),
257
          destBufferDims = ScaledSize(destBufferRect.Size(),
256
                                      aXResolution, aYResolution);
258
                                      aXResolution, aYResolution);
257
          bufferDimsChanged = PR_TRUE;
259
          bufferDimsChanged = PR_TRUE;
258
          destBuffer = CreateBuffer(aContentType, destBufferDims);
260
          destBuffer = CreateBuffer(aContentType, destBufferDims);
259
          if (!destBuffer)
261
          if (!destBuffer)
260
            return result;
262
            return result;
261
        }
263
        }
262
      } else {
264
      } else {
 Lines 267-283   ThebesLayerBuffer::BeginPaint(ThebesLaye Link Here 
267
      // No pixels are going to be kept. The whole visible region
269
      // No pixels are going to be kept. The whole visible region
268
      // will be redrawn, so we don't need to copy anything, so we don't
270
      // will be redrawn, so we don't need to copy anything, so we don't
269
      // set destBuffer.
271
      // set destBuffer.
270
      mBufferRect = destBufferRect;
272
      mBufferRect = destBufferRect;
271
      mBufferRotation = nsIntPoint(0,0);
273
      mBufferRotation = nsIntPoint(0,0);
272
    }
274
    }
273
  } else {
275
  } else {
274
    // The buffer's not big enough, so allocate a new one
276
    // The buffer's not big enough, so allocate a new one
275
    destBufferRect = visibleBounds;
277
    destBufferRect = neededBounds;
276
    destBufferDims = ScaledSize(destBufferRect.Size(),
278
    destBufferDims = ScaledSize(destBufferRect.Size(),
277
                                aXResolution, aYResolution);
279
                                aXResolution, aYResolution);
278
    bufferDimsChanged = PR_TRUE;
280
    bufferDimsChanged = PR_TRUE;
279
    destBuffer = CreateBuffer(aContentType, destBufferDims);
281
    destBuffer = CreateBuffer(aContentType, destBufferDims);
280
    if (!destBuffer)
282
    if (!destBuffer)
281
      return result;
283
      return result;
282
  }
284
  }
283
285
 Lines 300-315   ThebesLayerBuffer::BeginPaint(ThebesLaye Link Here 
300
302
301
    mBuffer = destBuffer.forget();
303
    mBuffer = destBuffer.forget();
302
    mBufferRect = destBufferRect;
304
    mBufferRect = destBufferRect;
303
    mBufferRotation = nsIntPoint(0,0);
305
    mBufferRotation = nsIntPoint(0,0);
304
  }
306
  }
305
  if (bufferDimsChanged) {
307
  if (bufferDimsChanged) {
306
    mBufferDims = destBufferDims;
308
    mBufferDims = destBufferDims;
307
  }
309
  }
310
  NS_ASSERTION(mEnableRotationOptimization || mBufferRotation == nsIntPoint(0,0),
311
               "Rotation disabled, but we have nonzero rotation?");
308
312
309
  nsIntRegion invalidate;
313
  nsIntRegion invalidate;
310
  invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
314
  invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
311
  result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
315
  result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
312
316
313
  result.mContext = GetContextForQuadrantUpdate(drawBounds,
317
  result.mContext = GetContextForQuadrantUpdate(drawBounds,
314
                                                aXResolution, aYResolution);
318
                                                aXResolution, aYResolution);
315
319
(-)a/gfx/layers/ThebesLayerBuffer.h (+15 lines)
Line     Link Here 
 Lines 80-103   public: Link Here 
80
    SizedToVisibleBounds,
80
    SizedToVisibleBounds,
81
    ContainsVisibleBounds
81
    ContainsVisibleBounds
82
  };
82
  };
83
83
84
  ThebesLayerBuffer(BufferSizePolicy aBufferSizePolicy)
84
  ThebesLayerBuffer(BufferSizePolicy aBufferSizePolicy)
85
    : mBufferDims(0,0)
85
    : mBufferDims(0,0)
86
    , mBufferRotation(0,0)
86
    , mBufferRotation(0,0)
87
    , mBufferSizePolicy(aBufferSizePolicy)
87
    , mBufferSizePolicy(aBufferSizePolicy)
88
    , mEnableRotationOptimization(PR_FALSE)
88
  {
89
  {
89
    MOZ_COUNT_CTOR(ThebesLayerBuffer);
90
    MOZ_COUNT_CTOR(ThebesLayerBuffer);
90
  }
91
  }
91
  virtual ~ThebesLayerBuffer()
92
  virtual ~ThebesLayerBuffer()
92
  {
93
  {
93
    MOZ_COUNT_DTOR(ThebesLayerBuffer);
94
    MOZ_COUNT_DTOR(ThebesLayerBuffer);
94
  }
95
  }
95
96
97
  void SetEnableRotationOptimization(PRBool aEnable)
98
  {
99
    if (mEnableRotationOptimization != aEnable) {
100
      // Force a new buffer to be created, since subclasses may decide
101
      // to create different buffer types depending on whether rotation is allowed
102
      Clear();
103
      mEnableRotationOptimization = aEnable;
104
    }
105
  }
106
96
  /**
107
  /**
97
   * Wipe out all retained contents. Call this when the entire
108
   * Wipe out all retained contents. Call this when the entire
98
   * buffer becomes invalid.
109
   * buffer becomes invalid.
99
   */
110
   */
100
  void Clear()
111
  void Clear()
101
  {
112
  {
102
    mBuffer = nsnull;
113
    mBuffer = nsnull;
103
    mBufferDims.SizeTo(0, 0);
114
    mBufferDims.SizeTo(0, 0);
 Lines 122-137   public: Link Here 
122
   * Start a drawing operation. This returns a PaintState describing what
133
   * Start a drawing operation. This returns a PaintState describing what
123
   * needs to be drawn to bring the buffer up to date in the visible region.
134
   * needs to be drawn to bring the buffer up to date in the visible region.
124
   * This queries aLayer to get the currently valid and visible regions.
135
   * This queries aLayer to get the currently valid and visible regions.
125
   * The returned mContext may be null if mRegionToDraw is empty.
136
   * The returned mContext may be null if mRegionToDraw is empty.
126
   * Otherwise it must not be null.
137
   * Otherwise it must not be null.
127
   * mRegionToInvalidate will contain mRegionToDraw.
138
   * mRegionToInvalidate will contain mRegionToDraw.
128
   */
139
   */
129
  PaintState BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
140
  PaintState BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
141
                        const nsIntRegion& aNeededRegion,
130
                        float aXResolution, float aYResolution);
142
                        float aXResolution, float aYResolution);
131
143
132
  /**
144
  /**
133
   * Return a new surface of |aSize| and |aType|.
145
   * Return a new surface of |aSize| and |aType|.
134
   */
146
   */
135
  virtual already_AddRefed<gfxASurface>
147
  virtual already_AddRefed<gfxASurface>
136
  CreateBuffer(ContentType aType, const nsIntSize& aSize) = 0;
148
  CreateBuffer(ContentType aType, const nsIntSize& aSize) = 0;
137
149
 Lines 214-227   private: Link Here 
214
   * So the pixel at mBufferRotation within the buffer is what gets painted at
226
   * So the pixel at mBufferRotation within the buffer is what gets painted at
215
   * mBufferRect.TopLeft().
227
   * mBufferRect.TopLeft().
216
   * This is "rotation" in the sense of rotating items in a linear buffer,
228
   * This is "rotation" in the sense of rotating items in a linear buffer,
217
   * where items falling off the end of the buffer are returned to the
229
   * where items falling off the end of the buffer are returned to the
218
   * buffer at the other end, not 2D rotation!
230
   * buffer at the other end, not 2D rotation!
219
   */
231
   */
220
  nsIntPoint            mBufferRotation;
232
  nsIntPoint            mBufferRotation;
221
  BufferSizePolicy      mBufferSizePolicy;
233
  BufferSizePolicy      mBufferSizePolicy;
234
235
protected:
236
  PRPackedBool          mEnableRotationOptimization;
222
};
237
};
223
238
224
}
239
}
225
}
240
}
226
241
227
#endif /* THEBESLAYERBUFFER_H_ */
242
#endif /* THEBESLAYERBUFFER_H_ */
(-)a/gfx/layers/basic/BasicLayers.cpp (-2 / +5 lines)
Line     Link Here 
 Lines 303-319   ContainerRemoveChild(Layer* aChild, Cont Link Here 
303
class BasicThebesLayer;
303
class BasicThebesLayer;
304
class BasicThebesLayerBuffer : public ThebesLayerBuffer {
304
class BasicThebesLayerBuffer : public ThebesLayerBuffer {
305
  typedef ThebesLayerBuffer Base;
305
  typedef ThebesLayerBuffer Base;
306
306
307
public:
307
public:
308
  BasicThebesLayerBuffer(BasicThebesLayer* aLayer)
308
  BasicThebesLayerBuffer(BasicThebesLayer* aLayer)
309
    : Base(ContainsVisibleBounds)
309
    : Base(ContainsVisibleBounds)
310
    , mLayer(aLayer)
310
    , mLayer(aLayer)
311
  {}
311
  {
312
    mEnableRotationOptimization = PR_TRUE;
313
  }
312
314
313
  virtual ~BasicThebesLayerBuffer()
315
  virtual ~BasicThebesLayerBuffer()
314
  {}
316
  {}
315
317
316
  using Base::BufferRect;
318
  using Base::BufferRect;
317
  using Base::BufferRotation;
319
  using Base::BufferRotation;
318
320
319
  /**
321
  /**
 Lines 348-363   public: Link Here 
348
350
349
private:
351
private:
350
  BasicThebesLayerBuffer(gfxASurface* aBuffer,
352
  BasicThebesLayerBuffer(gfxASurface* aBuffer,
351
                         const nsIntRect& aRect, const nsIntPoint& aRotation)
353
                         const nsIntRect& aRect, const nsIntPoint& aRotation)
352
    // The size policy doesn't really matter here; this constructor is
354
    // The size policy doesn't really matter here; this constructor is
353
    // intended to be used for creating temporaries
355
    // intended to be used for creating temporaries
354
    : ThebesLayerBuffer(ContainsVisibleBounds)
356
    : ThebesLayerBuffer(ContainsVisibleBounds)
355
  {
357
  {
358
    mEnableRotationOptimization = PR_TRUE;
356
    gfxIntSize sz = aBuffer->GetSize();
359
    gfxIntSize sz = aBuffer->GetSize();
357
    SetBuffer(aBuffer, nsIntSize(sz.width, sz.height), aRect, aRotation);
360
    SetBuffer(aBuffer, nsIntSize(sz.width, sz.height), aRect, aRotation);
358
  }
361
  }
359
362
360
  BasicThebesLayer* mLayer;
363
  BasicThebesLayer* mLayer;
361
};
364
};
362
365
363
class BasicThebesLayer : public ThebesLayer, BasicImplData {
366
class BasicThebesLayer : public ThebesLayer, BasicImplData {
 Lines 573-589   BasicThebesLayer::PaintThebes(gfxContext Link Here 
573
    return;
576
    return;
574
  }
577
  }
575
578
576
  {
579
  {
577
    gfxSize scale = aContext->CurrentMatrix().ScaleFactors(PR_TRUE);
580
    gfxSize scale = aContext->CurrentMatrix().ScaleFactors(PR_TRUE);
578
    float paintXRes = BasicManager()->XResolution() * gfxUtils::ClampToScaleFactor(scale.width);
581
    float paintXRes = BasicManager()->XResolution() * gfxUtils::ClampToScaleFactor(scale.width);
579
    float paintYRes = BasicManager()->YResolution() * gfxUtils::ClampToScaleFactor(scale.height);
582
    float paintYRes = BasicManager()->YResolution() * gfxUtils::ClampToScaleFactor(scale.height);
580
    Buffer::PaintState state =
583
    Buffer::PaintState state =
581
      mBuffer.BeginPaint(this, contentType, paintXRes, paintYRes);
584
      mBuffer.BeginPaint(this, contentType, mVisibleRegion, paintXRes, paintYRes);
582
    mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
585
    mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
583
586
584
    if (state.mContext) {
587
    if (state.mContext) {
585
      // The area that became invalid and is visible needs to be repainted
588
      // The area that became invalid and is visible needs to be repainted
586
      // (this could be the whole visible area if our buffer switched
589
      // (this could be the whole visible area if our buffer switched
587
      // from RGB to RGBA, because we might need to repaint with
590
      // from RGB to RGBA, because we might need to repaint with
588
      // subpixel AA)
591
      // subpixel AA)
589
      state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
592
      state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
(-)a/gfx/layers/opengl/ThebesLayerOGL.cpp (-41 / +84 lines)
Line     Link Here 
 Lines 47-74    Link Here 
47
#include "gfxTeeSurface.h"
47
#include "gfxTeeSurface.h"
48
48
49
namespace mozilla {
49
namespace mozilla {
50
namespace layers {
50
namespace layers {
51
51
52
using gl::GLContext;
52
using gl::GLContext;
53
using gl::TextureImage;
53
using gl::TextureImage;
54
54
55
static const int ALLOW_REPEAT = 0x01;
56
55
// BindAndDrawQuadWithTextureRect can work with either GL_REPEAT (preferred)
57
// BindAndDrawQuadWithTextureRect can work with either GL_REPEAT (preferred)
56
// or GL_CLAMP_TO_EDGE textures.  We select based on whether REPEAT is
58
// or GL_CLAMP_TO_EDGE textures.  We select based on whether REPEAT is
57
// valid for non-power-of-two textures -- if we have NPOT support we use it,
59
// valid for non-power-of-two textures -- if we have NPOT support we use it,
58
// otherwise we stick with CLAMP_TO_EDGE and decompose.
60
// otherwise we stick with CLAMP_TO_EDGE and decompose.
59
static already_AddRefed<TextureImage>
61
static already_AddRefed<TextureImage>
60
CreateClampOrRepeatTextureImage(GLContext *aGl,
62
CreateClampOrRepeatTextureImage(GLContext *aGl,
61
                                const nsIntSize& aSize,
63
                                const nsIntSize& aSize,
62
                                TextureImage::ContentType aContentType)
64
                                TextureImage::ContentType aContentType,
65
                                PRUint32 aFlags)
63
{
66
{
64
  GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
67
  GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
65
  if (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
68
  if ((aFlags & ALLOW_REPEAT) &&
66
      aGl->IsExtensionSupported(GLContext::OES_texture_npot))
69
      (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
70
       aGl->IsExtensionSupported(GLContext::OES_texture_npot)))
67
  {
71
  {
68
    wrapMode = LOCAL_GL_REPEAT;
72
    wrapMode = LOCAL_GL_REPEAT;
69
  }
73
  }
70
74
71
  return aGl->CreateTextureImage(aSize, aContentType, wrapMode);
75
  return aGl->CreateTextureImage(aSize, aContentType, wrapMode);
72
}
76
}
73
77
74
// |aTexCoordRect| is the rectangle from the texture that we want to
78
// |aTexCoordRect| is the rectangle from the texture that we want to
 Lines 151-167   public: Link Here 
151
  typedef ThebesLayerBuffer::PaintState PaintState;
155
  typedef ThebesLayerBuffer::PaintState PaintState;
152
156
153
  ThebesLayerBufferOGL(ThebesLayer* aLayer, LayerOGL* aOGLLayer)
157
  ThebesLayerBufferOGL(ThebesLayer* aLayer, LayerOGL* aOGLLayer)
154
    : mLayer(aLayer)
158
    : mLayer(aLayer)
155
    , mOGLLayer(aOGLLayer)
159
    , mOGLLayer(aOGLLayer)
156
  {}
160
  {}
157
  virtual ~ThebesLayerBufferOGL() {}
161
  virtual ~ThebesLayerBufferOGL() {}
158
162
163
  virtual void SetEnableRotationOptimization(PRBool aEnable) = 0;
164
159
  virtual PaintState BeginPaint(ContentType aContentType,
165
  virtual PaintState BeginPaint(ContentType aContentType,
166
                                const nsIntRegion& aNeededRegion,
160
                                float aXResolution,
167
                                float aXResolution,
161
                                float aYResolution) = 0;
168
                                float aYResolution) = 0;
162
169
163
  void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager);
170
  void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager);
164
171
165
  nsIntSize GetSize() {
172
  nsIntSize GetSize() {
166
    if (mTexImage)
173
    if (mTexImage)
167
      return mTexImage->GetSize();
174
      return mTexImage->GetSize();
 Lines 228-244   ThebesLayerBufferOGL::RenderTo(const nsI Link Here 
228
      DEBUG_GL_ERROR_CHECK(gl());
235
      DEBUG_GL_ERROR_CHECK(gl());
229
      alphaProgram->SetBlackTextureUnit(0);
236
      alphaProgram->SetBlackTextureUnit(0);
230
      alphaProgram->SetWhiteTextureUnit(1);
237
      alphaProgram->SetWhiteTextureUnit(1);
231
      program = alphaProgram;
238
      program = alphaProgram;
232
    } else {
239
    } else {
233
      // Note BGR: Cairo's image surfaces are always in what
240
      // Note BGR: Cairo's image surfaces are always in what
234
      // OpenGL and our shaders consider BGR format.
241
      // OpenGL and our shaders consider BGR format.
235
      ColorTextureLayerProgram *basicProgram =
242
      ColorTextureLayerProgram *basicProgram =
236
        aManager->GetBasicLayerProgram(mLayer->CanUseOpaqueSurface(),
243
        aManager->GetBasicLayerProgram(mTexImage->GetContentType() == gfxASurface::CONTENT_COLOR,
237
                                       mTexImage->IsRGB());
244
                                       mTexImage->IsRGB());
238
245
239
      basicProgram->Activate();
246
      basicProgram->Activate();
240
      DEBUG_GL_ERROR_CHECK(gl());
247
      DEBUG_GL_ERROR_CHECK(gl());
241
      basicProgram->SetTextureUnit(0);
248
      basicProgram->SetTextureUnit(0);
242
      program = basicProgram;
249
      program = basicProgram;
243
    }
250
    }
244
251
 Lines 286-320   public: Link Here 
286
293
287
  SurfaceBufferOGL(ThebesLayerOGL* aLayer)
294
  SurfaceBufferOGL(ThebesLayerOGL* aLayer)
288
    : ThebesLayerBufferOGL(aLayer, aLayer)
295
    : ThebesLayerBufferOGL(aLayer, aLayer)
289
    , ThebesLayerBuffer(SizedToVisibleBounds)
296
    , ThebesLayerBuffer(SizedToVisibleBounds)
290
  {
297
  {
291
  }
298
  }
292
  virtual ~SurfaceBufferOGL() {}
299
  virtual ~SurfaceBufferOGL() {}
293
300
301
  virtual void SetEnableRotationOptimization(PRBool aEnable)
302
  {
303
    ThebesLayerBuffer::SetEnableRotationOptimization(aEnable);
304
  }
305
294
  // ThebesLayerBufferOGL interface
306
  // ThebesLayerBufferOGL interface
295
  virtual PaintState BeginPaint(ContentType aContentType, 
307
  virtual PaintState BeginPaint(ContentType aContentType, 
296
                                float aXResolution, 
308
                                const nsIntRegion& aNeededRegion,
309
                                float aXResolution,
297
                                float aYResolution)
310
                                float aYResolution)
298
  {
311
  {
299
    // Let ThebesLayerBuffer do all the hard work for us! :D
312
    // Let ThebesLayerBuffer do all the hard work for us! :D
300
    return ThebesLayerBuffer::BeginPaint(mLayer, 
313
    return ThebesLayerBuffer::BeginPaint(mLayer, 
301
                                         aContentType, 
314
                                         aContentType, 
315
                                         aNeededRegion,
302
                                         aXResolution, 
316
                                         aXResolution, 
303
                                         aYResolution);
317
                                         aYResolution);
304
  }
318
  }
305
319
306
  // ThebesLayerBuffer interface
320
  // ThebesLayerBuffer interface
307
  virtual already_AddRefed<gfxASurface>
321
  virtual already_AddRefed<gfxASurface>
308
  CreateBuffer(ContentType aType, const nsIntSize& aSize)
322
  CreateBuffer(ContentType aType, const nsIntSize& aSize)
309
  {
323
  {
310
    NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");
324
    NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");
311
325
312
    mTexImage = CreateClampOrRepeatTextureImage(gl(), aSize, aType);
326
    mTexImage = CreateClampOrRepeatTextureImage(gl(), aSize, aType,
327
            mEnableRotationOptimization ? ALLOW_REPEAT : 0);
313
    return mTexImage ? mTexImage->GetBackingSurface() : nsnull;
328
    return mTexImage ? mTexImage->GetBackingSurface() : nsnull;
314
  }
329
  }
315
330
316
protected:
331
protected:
317
  virtual nsIntPoint GetOriginOffset() {
332
  virtual nsIntPoint GetOriginOffset() {
318
    return BufferRect().TopLeft() - BufferRotation();
333
    return BufferRect().TopLeft() - BufferRotation();
319
  }
334
  }
320
};
335
};
 Lines 326-345   protected: Link Here 
326
// and implementing them here using GL hacketry.
341
// and implementing them here using GL hacketry.
327
class BasicBufferOGL : public ThebesLayerBufferOGL
342
class BasicBufferOGL : public ThebesLayerBufferOGL
328
{
343
{
329
public:
344
public:
330
  BasicBufferOGL(ThebesLayerOGL* aLayer)
345
  BasicBufferOGL(ThebesLayerOGL* aLayer)
331
    : ThebesLayerBufferOGL(aLayer, aLayer)
346
    : ThebesLayerBufferOGL(aLayer, aLayer)
332
    , mBufferRect(0,0,0,0)
347
    , mBufferRect(0,0,0,0)
333
    , mBufferRotation(0,0)
348
    , mBufferRotation(0,0)
349
    , mEnableRotationOptimization(PR_FALSE)
334
  {}
350
  {}
335
  virtual ~BasicBufferOGL() {}
351
  virtual ~BasicBufferOGL() {}
336
352
353
  virtual void SetEnableRotationOptimization(PRBool aEnable)
354
  {
355
    mEnableRotationOptimization = aEnable;
356
  }
337
  virtual PaintState BeginPaint(ContentType aContentType,
357
  virtual PaintState BeginPaint(ContentType aContentType,
358
                                const nsIntRegion& aNeededRegion,
338
                                float aXResolution,
359
                                float aXResolution,
339
                                float aYResolution);
360
                                float aYResolution);
340
361
341
protected:
362
protected:
342
  enum XSide {
363
  enum XSide {
343
    LEFT, RIGHT
364
    LEFT, RIGHT
344
  };
365
  };
345
  enum YSide {
366
  enum YSide {
 Lines 349-364   protected: Link Here 
349
370
350
  virtual nsIntPoint GetOriginOffset() {
371
  virtual nsIntPoint GetOriginOffset() {
351
    return mBufferRect.TopLeft() - mBufferRotation;
372
    return mBufferRect.TopLeft() - mBufferRotation;
352
  }
373
  }
353
374
354
private:
375
private:
355
  nsIntRect mBufferRect;
376
  nsIntRect mBufferRect;
356
  nsIntPoint mBufferRotation;
377
  nsIntPoint mBufferRotation;
378
  PRPackedBool mEnableRotationOptimization;
357
};
379
};
358
380
359
static void
381
static void
360
WrapRotationAxis(PRInt32* aRotationPoint, PRInt32 aSize)
382
WrapRotationAxis(PRInt32* aRotationPoint, PRInt32 aSize)
361
{
383
{
362
  if (*aRotationPoint < 0) {
384
  if (*aRotationPoint < 0) {
363
    *aRotationPoint += aSize;
385
    *aRotationPoint += aSize;
364
  } else if (*aRotationPoint >= aSize) {
386
  } else if (*aRotationPoint >= aSize) {
 Lines 397-513   ScaledSize(const nsIntSize& aSize, float Link Here 
397
419
398
  nsIntRect rect(0, 0, aSize.width, aSize.height);
420
  nsIntRect rect(0, 0, aSize.width, aSize.height);
399
  rect.ScaleRoundOut(aXScale, aYScale);
421
  rect.ScaleRoundOut(aXScale, aYScale);
400
  return rect.Size();
422
  return rect.Size();
401
}
423
}
402
424
403
BasicBufferOGL::PaintState
425
BasicBufferOGL::PaintState
404
BasicBufferOGL::BeginPaint(ContentType aContentType,
426
BasicBufferOGL::BeginPaint(ContentType aContentType,
427
                           const nsIntRegion& aNeededRegion,
405
                           float aXResolution,
428
                           float aXResolution,
406
                           float aYResolution)
429
                           float aYResolution)
407
{
430
{
408
  PaintState result;
431
  PaintState result;
409
432
410
  result.mRegionToDraw.Sub(mLayer->GetVisibleRegion(), mLayer->GetValidRegion());
433
  result.mRegionToDraw.Sub(aNeededRegion, mLayer->GetValidRegion());
411
  
434
  
412
  float curXRes = mLayer->GetXResolution();
435
  float curXRes = mLayer->GetXResolution();
413
  float curYRes = mLayer->GetYResolution();
436
  float curYRes = mLayer->GetYResolution();
414
  Layer::SurfaceMode mode = mLayer->GetSurfaceMode();
437
  Layer::SurfaceMode mode = mLayer->GetSurfaceMode();
415
438
416
  if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
439
  if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
417
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
440
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
418
    mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
441
    mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
419
#else
442
#else
420
    if (!mLayer->GetParent() || !mLayer->GetParent()->SupportsComponentAlphaChildren()) {
443
    if (!mLayer->GetParent() || !mLayer->GetParent()->SupportsComponentAlphaChildren()) {
421
      mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
444
      mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
422
    } else {
445
    } else {
423
      aContentType = gfxASurface::CONTENT_COLOR;
446
      aContentType = gfxASurface::CONTENT_COLOR;
424
    }
447
    }
425
#endif
448
#endif
426
  }
449
  }
450
  if (mode == Layer::SURFACE_OPAQUE && aContentType == gfxASurface::CONTENT_COLOR_ALPHA) {
451
    // The caller may be forcing us to use an RGBA texture
452
    mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
453
  }
427
454
428
  if (!mTexImage || mTexImage->GetContentType() != aContentType ||
455
  if (!mTexImage || mTexImage->GetContentType() != aContentType ||
429
      aXResolution != curXRes || aYResolution != curYRes ||
456
      aXResolution != curXRes || aYResolution != curYRes ||
430
      (mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nsnull)) {
457
      (mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nsnull)) {
431
    // We're effectively clearing the valid region, so we need to draw
458
    // We're effectively clearing the valid region, so we need to draw
432
    // the entire visible region now.
459
    // the entire needed region now.
433
    //
460
    //
434
    // XXX/cjones: a possibly worthwhile optimization to keep in mind
461
    // XXX/cjones: a possibly worthwhile optimization to keep in mind
435
    // is to re-use buffers when the resolution and visible region
462
    // is to re-use buffers when the resolution and visible region
436
    // have changed in such a way that the buffer size stays the same.
463
    // have changed in such a way that the buffer size stays the same.
437
    // It might make even more sense to allocate buffers from a
464
    // It might make even more sense to allocate buffers from a
438
    // recyclable pool, so that we could keep this logic simple and
465
    // recyclable pool, so that we could keep this logic simple and
439
    // still get back the same buffer.
466
    // still get back the same buffer.
440
    result.mRegionToDraw = mLayer->GetVisibleRegion();
467
    result.mRegionToDraw = aNeededRegion;
441
    result.mRegionToInvalidate = mLayer->GetValidRegion();
468
    result.mRegionToInvalidate = mLayer->GetValidRegion();
442
    mTexImage = nsnull;
469
    mTexImage = nsnull;
443
    mTexImageOnWhite = nsnull;
470
    mTexImageOnWhite = nsnull;
444
    mBufferRect.SetRect(0, 0, 0, 0);
471
    mBufferRect.SetRect(0, 0, 0, 0);
445
    mBufferRotation.MoveTo(0, 0);
472
    mBufferRotation.MoveTo(0, 0);
446
  }
473
  }
447
474
448
  if (result.mRegionToDraw.IsEmpty())
475
  if (result.mRegionToDraw.IsEmpty())
449
    return result;
476
    return result;
450
477
451
  nsIntRect visibleBounds = mLayer->GetVisibleRegion().GetBounds();
478
  nsIntRect neededBounds = aNeededRegion.GetBounds();
452
  nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
479
  nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
453
  nsIntSize destBufferDims = ScaledSize(visibleBounds.Size(),
480
  nsIntSize destBufferDims = ScaledSize(neededBounds.Size(),
454
                                        aXResolution, aYResolution);
481
                                        aXResolution, aYResolution);
455
  
482
  
456
  if (destBufferDims.width > gl()->GetMaxTextureSize() ||
483
  if (destBufferDims.width > gl()->GetMaxTextureSize() ||
457
      destBufferDims.height > gl()->GetMaxTextureSize()) {
484
      destBufferDims.height > gl()->GetMaxTextureSize()) {
458
    return result;
485
    return result;
459
  }
486
  }
460
487
461
  nsRefPtr<TextureImage> destBuffer;
488
  nsRefPtr<TextureImage> destBuffer;
462
  nsRefPtr<TextureImage> destBufferOnWhite;
489
  nsRefPtr<TextureImage> destBufferOnWhite;
463
  nsIntRect destBufferRect;
490
  nsIntRect destBufferRect;
491
  PRUint32 textureFlags = mEnableRotationOptimization ? ALLOW_REPEAT : 0;
464
492
465
  if (visibleBounds.Size() <= mBufferRect.Size()) {
493
  if (neededBounds.Size() <= mBufferRect.Size() &&
494
      mTexImage &&
495
      (mTexImage->GetWrapMode() == LOCAL_GL_CLAMP_TO_EDGE || mEnableRotationOptimization)) {
466
    NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
496
    NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
467
                 "resolution changes must clear the buffer!");
497
                 "resolution changes must clear the buffer!");
468
    // The current buffer is big enough to hold the visible area.
498
    // The current buffer is big enough to hold the visible area.
469
    if (mBufferRect.Contains(visibleBounds)) {
499
    if (mBufferRect.Contains(neededBounds)) {
470
      // We don't need to adjust mBufferRect.
500
      // We don't need to adjust mBufferRect.
471
      destBufferRect = mBufferRect;
501
      destBufferRect = mBufferRect;
472
    } else {
502
    } else {
473
      // The buffer's big enough but doesn't contain everything that's
503
      // The buffer's big enough but doesn't contain everything that's
474
      // going to be visible. We'll move it.
504
      // going to be visible. We'll move it.
475
      destBufferRect = nsIntRect(visibleBounds.TopLeft(), mBufferRect.Size());
505
      destBufferRect = nsIntRect(neededBounds.TopLeft(), mBufferRect.Size());
476
    }
506
    }
477
    nsIntRect keepArea;
507
    nsIntRect keepArea;
478
    if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
508
    if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
479
      // Set mBufferRotation so that the pixels currently in mBuffer
509
      // Set mBufferRotation so that the pixels currently in mBuffer
480
      // will still be rendered in the right place when mBufferRect
510
      // will still be rendered in the right place when mBufferRect
481
      // changes to destBufferRect.
511
      // changes to destBufferRect.
482
      nsIntPoint newRotation = mBufferRotation +
512
      nsIntPoint newRotation = mBufferRotation +
483
        (destBufferRect.TopLeft() - mBufferRect.TopLeft());
513
        (destBufferRect.TopLeft() - mBufferRect.TopLeft());
484
      WrapRotationAxis(&newRotation.x, mBufferRect.width);
514
      WrapRotationAxis(&newRotation.x, mBufferRect.width);
485
      WrapRotationAxis(&newRotation.y, mBufferRect.height);
515
      WrapRotationAxis(&newRotation.y, mBufferRect.height);
486
      NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
516
      NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
487
                   "newRotation out of bounds");
517
                   "newRotation out of bounds");
488
      PRInt32 xBoundary = destBufferRect.XMost() - newRotation.x;
518
      PRInt32 xBoundary = destBufferRect.XMost() - newRotation.x;
489
      PRInt32 yBoundary = destBufferRect.YMost() - newRotation.y;
519
      PRInt32 yBoundary = destBufferRect.YMost() - newRotation.y;
490
      if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) ||
520
      if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) ||
491
          (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost())) {
521
          (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) ||
522
          (!mEnableRotationOptimization && newRotation != nsIntPoint(0,0))) {
492
        // The stuff we need to redraw will wrap around an edge of the
523
        // The stuff we need to redraw will wrap around an edge of the
493
        // buffer, so we will need to do a self-copy
524
        // buffer, so we will need to do a self-copy
494
        // If mBufferRotation == nsIntPoint(0,0) we could do a real
525
        // If mBufferRotation == nsIntPoint(0,0) we could do a real
495
        // self-copy but we're not going to do that in GL yet.
526
        // self-copy but we're not going to do that in GL yet.
496
        // We can't do a real self-copy because the buffer is rotated.
527
        // We can't do a real self-copy because the buffer is rotated.
497
        // So allocate a new buffer for the destination.
528
        // So allocate a new buffer for the destination.
498
        destBufferRect = visibleBounds;
529
        destBufferRect = neededBounds;
499
        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
530
        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType, textureFlags);
500
        DEBUG_GL_ERROR_CHECK(gl());
531
        DEBUG_GL_ERROR_CHECK(gl());
501
        if (!destBuffer)
532
        if (!destBuffer)
502
          return result;
533
          return result;
503
        if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
534
        if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
504
          destBufferOnWhite =
535
          destBufferOnWhite =
505
            CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
536
            CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType, textureFlags);
506
          DEBUG_GL_ERROR_CHECK(gl());
537
          DEBUG_GL_ERROR_CHECK(gl());
507
          if (!destBufferOnWhite)
538
          if (!destBufferOnWhite)
508
            return result;
539
            return result;
509
        }
540
        }
510
      } else {
541
      } else {
511
        mBufferRect = destBufferRect;
542
        mBufferRect = destBufferRect;
512
        mBufferRotation = newRotation;
543
        mBufferRotation = newRotation;
513
      }
544
      }
 Lines 515-539   BasicBufferOGL::BeginPaint(ContentType a Link Here 
515
      // No pixels are going to be kept. The whole visible region
546
      // No pixels are going to be kept. The whole visible region
516
      // will be redrawn, so we don't need to copy anything, so we don't
547
      // will be redrawn, so we don't need to copy anything, so we don't
517
      // set destBuffer.
548
      // set destBuffer.
518
      mBufferRect = destBufferRect;
549
      mBufferRect = destBufferRect;
519
      mBufferRotation = nsIntPoint(0,0);
550
      mBufferRotation = nsIntPoint(0,0);
520
    }
551
    }
521
  } else {
552
  } else {
522
    // The buffer's not big enough, so allocate a new one
553
    // The buffer's not big enough, so allocate a new one
523
    destBufferRect = visibleBounds;
554
    destBufferRect = neededBounds;
524
    destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
555
    destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType, textureFlags);
525
    DEBUG_GL_ERROR_CHECK(gl());
556
    DEBUG_GL_ERROR_CHECK(gl());
526
    if (!destBuffer)
557
    if (!destBuffer)
527
      return result;
558
      return result;
528
559
529
    if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
560
    if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
530
      destBufferOnWhite = 
561
      destBufferOnWhite = 
531
        CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
562
        CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType, textureFlags);
532
      DEBUG_GL_ERROR_CHECK(gl());
563
      DEBUG_GL_ERROR_CHECK(gl());
533
      if (!destBufferOnWhite)
564
      if (!destBufferOnWhite)
534
        return result;
565
        return result;
535
    }
566
    }
536
  }
567
  }
537
568
538
  if (!destBuffer && !mTexImage) {
569
  if (!destBuffer && !mTexImage) {
539
    return result;
570
    return result;
 Lines 560-591   BasicBufferOGL::BeginPaint(ContentType a Link Here 
560
                               destBuffer, dstRect);
591
                               destBuffer, dstRect);
561
        if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
592
        if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
562
          destBufferOnWhite->Resize(size);
593
          destBufferOnWhite->Resize(size);
563
          gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
594
          gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
564
                                 destBufferOnWhite, dstRect);
595
                                 destBufferOnWhite, dstRect);
565
        }
596
        }
566
      } else {
597
      } else {
567
        // can't blit, just draw everything
598
        // can't blit, just draw everything
568
        destBufferRect = visibleBounds;
599
        destBufferRect = neededBounds;
569
        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
600
        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType, textureFlags);
570
        if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
601
        if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
571
          destBufferOnWhite = 
602
          destBufferOnWhite = 
572
            CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
603
            CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType, textureFlags);
573
        }
604
        }
574
      }
605
      }
575
    }
606
    }
576
607
577
    mTexImage = destBuffer.forget();
608
    mTexImage = destBuffer.forget();
578
    if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
609
    if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
579
      mTexImageOnWhite = destBufferOnWhite.forget();
610
      mTexImageOnWhite = destBufferOnWhite.forget();
580
    }
611
    }
581
    mBufferRect = destBufferRect;
612
    mBufferRect = destBufferRect;
582
    mBufferRotation = nsIntPoint(0,0);
613
    mBufferRotation = nsIntPoint(0,0);
583
  }
614
  }
615
  NS_ASSERTION(mEnableRotationOptimization || mBufferRotation == nsIntPoint(0,0),
616
               "Rotation disabled, but we have nonzero rotation?");
584
617
585
  nsIntRegion invalidate;
618
  nsIntRegion invalidate;
586
  invalidate.Sub(mLayer->GetValidRegion(), destBufferRect);
619
  invalidate.Sub(mLayer->GetValidRegion(), destBufferRect);
587
  result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
620
  result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
588
621
589
  // Figure out which quadrant to draw in
622
  // Figure out which quadrant to draw in
590
  PRInt32 xBoundary = mBufferRect.XMost() - mBufferRotation.x;
623
  PRInt32 xBoundary = mBufferRect.XMost() - mBufferRotation.x;
591
  PRInt32 yBoundary = mBufferRect.YMost() - mBufferRotation.y;
624
  PRInt32 yBoundary = mBufferRect.YMost() - mBufferRotation.y;
 Lines 625-641   BasicBufferOGL::BeginPaint(ContentType a Link Here 
625
    // be incorrect.
658
    // be incorrect.
626
    surf->SetAllowUseAsSource(PR_FALSE);
659
    surf->SetAllowUseAsSource(PR_FALSE);
627
    result.mContext = new gfxContext(surf);
660
    result.mContext = new gfxContext(surf);
628
  } else {
661
  } else {
629
    result.mContext = new gfxContext(mTexImage->BeginUpdate(result.mRegionToDraw));
662
    result.mContext = new gfxContext(mTexImage->BeginUpdate(result.mRegionToDraw));
630
    if (mTexImage->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
663
    if (mTexImage->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
631
      gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
664
      gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
632
      result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
665
      result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
633
      result.mContext->Fill();
666
      result.mContext->Paint();
634
      result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
667
      result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
635
    }
668
    }
636
  }
669
  }
637
  if (!result.mContext) {
670
  if (!result.mContext) {
638
    NS_WARNING("unable to get context for update");
671
    NS_WARNING("unable to get context for update");
639
    return result;
672
    return result;
640
  }
673
  }
641
  result.mContext->Scale(aXResolution, aYResolution);
674
  result.mContext->Scale(aXResolution, aYResolution);
 Lines 719-763   ThebesLayerOGL::RenderLayer(int aPreviou Link Here 
719
  mOGLManager->MakeCurrent();
752
  mOGLManager->MakeCurrent();
720
  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
753
  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
721
754
722
  TextureImage::ContentType contentType =
755
  TextureImage::ContentType contentType =
723
    CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
756
    CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
724
                            gfxASurface::CONTENT_COLOR_ALPHA;
757
                            gfxASurface::CONTENT_COLOR_ALPHA;
725
758
726
  const gfx3DMatrix& transform = GetEffectiveTransform();
759
  const gfx3DMatrix& transform = GetEffectiveTransform();
760
  nsIntRegion neededRegion = mVisibleRegion;
727
  gfxMatrix transform2d;
761
  gfxMatrix transform2d;
728
  gfxSize scale(1.0, 1.0);
762
  gfxSize scale(1.0, 1.0);
763
  float paintXRes = 1.0;
764
  float paintYRes = 1.0;
765
  bool willResample;
729
  if (transform.Is2D(&transform2d)) {
766
  if (transform.Is2D(&transform2d)) {
730
    scale = transform2d.ScaleFactors(PR_TRUE);
767
    scale = transform2d.ScaleFactors(PR_TRUE);
768
    paintXRes = gfxUtils::ClampToScaleFactor(scale.width);
769
    paintYRes = gfxUtils::ClampToScaleFactor(scale.height);
770
    transform2d.Scale(1.0/paintXRes, 1.0/paintYRes);
771
    willResample = transform2d.HasNonIntegerTranslation();
772
  } else {
773
    willResample = true;
731
  }
774
  }
732
  float paintXRes = gfxUtils::ClampToScaleFactor(scale.width);
775
  if (willResample && neededRegion.GetNumRects() > 1) {
733
  float paintYRes = gfxUtils::ClampToScaleFactor(scale.height);
776
    neededRegion = mVisibleRegion.GetBounds();
777
    contentType = gfxASurface::CONTENT_COLOR_ALPHA;
778
  }
734
779
735
  Buffer::PaintState state = mBuffer->BeginPaint(contentType, paintXRes, paintYRes);
780
  mBuffer->SetEnableRotationOptimization(!willResample);
781
  Buffer::PaintState state =
782
    mBuffer->BeginPaint(contentType, neededRegion, paintXRes, paintYRes);
736
  mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
783
  mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
737
784
738
  if (state.mContext) {
785
  if (state.mContext) {
739
    state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
786
    state.mRegionToInvalidate.And(state.mRegionToInvalidate, neededRegion);
740
    mXResolution = paintXRes;
787
    mXResolution = paintXRes;
741
    mYResolution = paintYRes;
788
    mYResolution = paintYRes;
742
789
743
    LayerManager::DrawThebesLayerCallback callback =
790
    LayerManager::DrawThebesLayerCallback callback =
744
      mOGLManager->GetThebesLayerCallback();
791
      mOGLManager->GetThebesLayerCallback();
745
    if (!callback) {
792
    if (!callback) {
746
      NS_ERROR("GL should never need to update ThebesLayers in an empty transaction");
793
      NS_ERROR("GL should never need to update ThebesLayers in an empty transaction");
747
    } else {
794
    } else {
748
      void* callbackData = mOGLManager->GetThebesLayerCallbackData();
795
      void* callbackData = mOGLManager->GetThebesLayerCallbackData();
749
      callback(this, state.mContext, state.mRegionToDraw,
796
      callback(this, state.mContext, state.mRegionToDraw,
750
               state.mRegionToInvalidate, callbackData);
797
               state.mRegionToInvalidate, callbackData);
751
      // Everything that's visible has been validated. Do this instead of
798
      // Everything that's visible has been validated. Do this instead of
752
      // OR-ing with aRegionToDraw, since that can lead to a very complex region
799
      // OR-ing with aRegionToDraw, since that can lead to a very complex region
753
      // here (OR doesn't automatically simplify to the simplest possible
800
      // here (OR doesn't automatically simplify to the simplest possible
754
      // representation of a region.)
801
      // representation of a region.)
755
      mValidRegion.Or(mValidRegion, mVisibleRegion);
802
      mValidRegion.Or(mValidRegion, neededRegion);
756
    }
803
    }
757
  }
804
  }
758
805
759
  DEBUG_GL_ERROR_CHECK(gl());
806
  DEBUG_GL_ERROR_CHECK(gl());
760
807
761
  gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
808
  gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
762
  mBuffer->RenderTo(aOffset, mOGLManager);
809
  mBuffer->RenderTo(aOffset, mOGLManager);
763
  DEBUG_GL_ERROR_CHECK(gl());
810
  DEBUG_GL_ERROR_CHECK(gl());
 Lines 780-808   ThebesLayerOGL::IsEmpty() Link Here 
780
827
781
class ShadowBufferOGL : public ThebesLayerBufferOGL
828
class ShadowBufferOGL : public ThebesLayerBufferOGL
782
{
829
{
783
public:
830
public:
784
  ShadowBufferOGL(ShadowThebesLayerOGL* aLayer)
831
  ShadowBufferOGL(ShadowThebesLayerOGL* aLayer)
785
    : ThebesLayerBufferOGL(aLayer, aLayer)
832
    : ThebesLayerBufferOGL(aLayer, aLayer)
786
  {}
833
  {}
787
834
788
  virtual PaintState BeginPaint(ContentType aContentType, float, float) {
835
  virtual void SetEnableRotationOptimization(PRBool aEnable) {}
836
  virtual PaintState BeginPaint(ContentType aContentType,
837
                                const nsIntRegion&, float, float) {
789
    NS_RUNTIMEABORT("can't BeginPaint for a shadow layer");
838
    NS_RUNTIMEABORT("can't BeginPaint for a shadow layer");
790
    return PaintState();
839
    return PaintState();
791
  }
840
  }
792
841
793
  void
794
  CreateTexture(ContentType aType, const nsIntSize& aSize)
795
  {
796
    NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");
797
798
    mTexImage = CreateClampOrRepeatTextureImage(gl(), aSize, aType);
799
  }
800
801
  void Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
842
  void Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
802
              const nsIntRect& aRect, const nsIntPoint& aRotation);
843
              const nsIntRect& aRect, const nsIntPoint& aRotation);
803
844
804
protected:
845
protected:
805
  virtual nsIntPoint GetOriginOffset() {
846
  virtual nsIntPoint GetOriginOffset() {
806
    return mBufferRect.TopLeft() - mBufferRotation;
847
    return mBufferRect.TopLeft() - mBufferRotation;
807
  }
848
  }
808
849
 Lines 812-829   private: Link Here 
812
};
853
};
813
854
814
void
855
void
815
ShadowBufferOGL::Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
856
ShadowBufferOGL::Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
816
                        const nsIntRect& aRect, const nsIntPoint& aRotation)
857
                        const nsIntRect& aRect, const nsIntPoint& aRotation)
817
{
858
{
818
  gfxIntSize size = aUpdate->GetSize();
859
  gfxIntSize size = aUpdate->GetSize();
819
  if (GetSize() != nsIntSize(size.width, size.height)) {
860
  if (GetSize() != nsIntSize(size.width, size.height)) {
820
    CreateTexture(aUpdate->GetContentType(),
861
    // XXX we should do something here to decide whether to use REPEAT or not,
821
                  nsIntSize(size.width, size.height));
862
    // but I'm not sure what
863
    mTexImage = CreateClampOrRepeatTextureImage(gl(),
864
      nsIntSize(size.width, size.height), aUpdate->GetContentType(), ALLOW_REPEAT);
822
  }
865
  }
823
866
824
  nsIntRegion destRegion(aUpdated);
867
  nsIntRegion destRegion(aUpdated);
825
  // aUpdated is in screen coordinates.  Move it so that the layer's
868
  // aUpdated is in screen coordinates.  Move it so that the layer's
826
  // top-left is 0,0
869
  // top-left is 0,0
827
  nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft();
870
  nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft();
828
  destRegion.MoveBy(-visTopLeft);
871
  destRegion.MoveBy(-visTopLeft);
829
872

Return to bug 635373