Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: Source/core/platform/graphics/gpu/DrawingBuffer.cpp

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2010, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32
33 #include "core/platform/graphics/gpu/DrawingBuffer.h"
34
35 #include <algorithm>
36 #include "core/platform/graphics/Extensions3D.h"
37 #include "core/platform/graphics/GraphicsLayer.h"
38 #include "platform/TraceEvent.h"
39 #include "public/platform/Platform.h"
40 #include "public/platform/WebCompositorSupport.h"
41 #include "public/platform/WebExternalBitmap.h"
42 #include "public/platform/WebExternalTextureLayer.h"
43 #include "public/platform/WebGraphicsContext3D.h"
44
45 using namespace std;
46
47 namespace WebCore {
48
49 // Global resource ceiling (expressed in terms of pixels) for DrawingBuffer crea tion and resize.
50 // When this limit is set, DrawingBuffer::create() and DrawingBuffer::reset() ca lls that would
51 // exceed the global cap will instead clear the buffer.
52 static const int s_maximumResourceUsePixels = 16 * 1024 * 1024;
53 static int s_currentResourceUsePixels = 0;
54 static const float s_resourceAdjustedRatio = 0.5;
55
56 static const bool s_allowContextEvictionOnCreate = true;
57 static const int s_maxScaleAttempts = 3;
58
59 class ScopedTextureUnit0BindingRestorer {
60 public:
61 ScopedTextureUnit0BindingRestorer(GraphicsContext3D* context, GC3Denum activ eTextureUnit, Platform3DObject textureUnitZeroId)
62 : m_context(context)
63 , m_oldActiveTextureUnit(activeTextureUnit)
64 , m_oldTextureUnitZeroId(textureUnitZeroId)
65 {
66 m_context->activeTexture(GraphicsContext3D::TEXTURE0);
67 }
68 ~ScopedTextureUnit0BindingRestorer()
69 {
70 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_oldTextureUnitZe roId);
71 m_context->activeTexture(m_oldActiveTextureUnit);
72 }
73
74 private:
75 GraphicsContext3D* m_context;
76 GC3Denum m_oldActiveTextureUnit;
77 Platform3DObject m_oldTextureUnitZeroId;
78 };
79
80 PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, cons t IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManag er> contextEvictionManager)
81 {
82 Extensions3D* extensions = context->extensions();
83 bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit" )
84 && extensions->supports("GL_ANGLE_framebuffer_multisample")
85 && extensions->supports("GL_OES_rgb8_rgba8");
86 if (multisampleSupported) {
87 extensions->ensureEnabled("GL_ANGLE_framebuffer_blit");
88 extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
89 extensions->ensureEnabled("GL_OES_rgb8_rgba8");
90 }
91 bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth _stencil");
92 if (packedDepthStencilSupported)
93 extensions->ensureEnabled("GL_OES_packed_depth_stencil");
94
95 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, si ze, multisampleSupported, packedDepthStencilSupported, preserve, contextEviction Manager));
96 return drawingBuffer.release();
97 }
98
99 DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
100 const IntSize& size,
101 bool multisampleExtensionSupported,
102 bool packedDepthStencilExtensionSupported,
103 PreserveDrawingBuffer preserve,
104 PassRefPtr<ContextEvictionManager> contextEvictionM anager)
105 : m_preserveDrawingBuffer(preserve)
106 , m_scissorEnabled(false)
107 , m_texture2DBinding(0)
108 , m_framebufferBinding(0)
109 , m_activeTextureUnit(GraphicsContext3D::TEXTURE0)
110 , m_context(context)
111 , m_size(-1, -1)
112 , m_multisampleExtensionSupported(multisampleExtensionSupported)
113 , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupporte d)
114 , m_fbo(0)
115 , m_colorBuffer(0)
116 , m_frontColorBuffer(0)
117 , m_depthStencilBuffer(0)
118 , m_depthBuffer(0)
119 , m_stencilBuffer(0)
120 , m_multisampleFBO(0)
121 , m_multisampleColorBuffer(0)
122 , m_contentsChanged(true)
123 , m_contentsChangeCommitted(false)
124 , m_internalColorFormat(0)
125 , m_colorFormat(0)
126 , m_internalRenderbufferFormat(0)
127 , m_maxTextureSize(0)
128 , m_contextEvictionManager(contextEvictionManager)
129 {
130 // Used by browser tests to detect the use of a DrawingBuffer.
131 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation");
132 initialize(size);
133 }
134
135 DrawingBuffer::~DrawingBuffer()
136 {
137 releaseResources();
138 }
139
140 void DrawingBuffer::markContentsChanged()
141 {
142 m_contentsChanged = true;
143 m_contentsChangeCommitted = false;
144 }
145
146 blink::WebGraphicsContext3D* DrawingBuffer::context()
147 {
148 if (!m_context)
149 return 0;
150 return m_context->webContext();
151 }
152
153 bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap)
154 {
155 if (!m_context || !m_contentsChanged || !m_lastColorBuffer)
156 return false;
157
158 m_context->makeContextCurrent();
159
160 // Resolve the multisampled buffer into the texture referenced by m_lastColo rBuffer mailbox.
161 if (multisample())
162 commit();
163
164 if (bitmap) {
165 bitmap->setSize(size());
166
167 unsigned char* pixels = bitmap->pixels();
168 bool needPremultiply = m_attributes.alpha && !m_attributes.premultiplied Alpha;
169 GraphicsContext3D::AlphaOp op = needPremultiply ? GraphicsContext3D::Alp haDoPremultiply : GraphicsContext3D::AlphaDoNothing;
170 if (pixels)
171 m_context->readBackFramebuffer(pixels, size().width(), size().height (), GraphicsContext3D::ReadbackSkia, op);
172 }
173
174 // We must restore the texture binding since creating new textures,
175 // consuming and producing mailboxes changes it.
176 ScopedTextureUnit0BindingRestorer restorer(m_context.get(), m_activeTextureU nit, m_texture2DBinding);
177
178 // First try to recycle an old buffer.
179 RefPtr<MailboxInfo> nextFrontColorBuffer = recycledMailbox();
180
181 // No buffer available to recycle, create a new one.
182 if (!nextFrontColorBuffer) {
183 unsigned newColorBuffer = createColorTexture(m_size);
184 // Bad things happened, abandon ship.
185 if (!newColorBuffer)
186 return false;
187
188 nextFrontColorBuffer = createNewMailbox(newColorBuffer);
189 }
190
191 if (m_preserveDrawingBuffer == Discard) {
192 m_colorBuffer = nextFrontColorBuffer->textureId;
193 swap(nextFrontColorBuffer, m_lastColorBuffer);
194 // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a
195 // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding.
196 // If this stops being true at some point, we should track the current f ramebuffer binding in the DrawingBuffer and restore
197 // it after attaching the new back buffer here.
198 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
199 m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, Graphics Context3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
200 } else {
201 Extensions3D* extensions = m_context->extensions();
202 extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_colorBu ffer, nextFrontColorBuffer->textureId, 0, GraphicsContext3D::RGBA, GraphicsConte xt3D::UNSIGNED_BYTE);
203 }
204
205 if (multisample() && !m_framebufferBinding)
206 bind();
207 else
208 restoreFramebufferBinding();
209
210 m_contentsChanged = false;
211
212 context()->bindTexture(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer-> textureId);
213 context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, nextFrontCo lorBuffer->mailbox.name);
214 context()->flush();
215 m_context->markLayerComposited();
216
217 *outMailbox = nextFrontColorBuffer->mailbox;
218 m_frontColorBuffer = nextFrontColorBuffer->textureId;
219 return true;
220 }
221
222 void DrawingBuffer::mailboxReleased(const blink::WebExternalTextureMailbox& mail box)
223 {
224 for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
225 RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i];
226 if (!memcmp(mailboxInfo->mailbox.name, mailbox.name, sizeof(mailbox.nam e))) {
227 mailboxInfo->mailbox.syncPoint = mailbox.syncPoint;
228 m_recycledMailboxes.append(mailboxInfo.release());
229 return;
230 }
231 }
232 ASSERT_NOT_REACHED();
233 }
234
235 PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox()
236 {
237 if (!m_context || m_recycledMailboxes.isEmpty())
238 return PassRefPtr<MailboxInfo>();
239
240 RefPtr<MailboxInfo> mailboxInfo = m_recycledMailboxes.last().release();
241 m_recycledMailboxes.removeLast();
242
243 if (mailboxInfo->mailbox.syncPoint) {
244 context()->waitSyncPoint(mailboxInfo->mailbox.syncPoint);
245 mailboxInfo->mailbox.syncPoint = 0;
246 }
247
248 context()->bindTexture(GraphicsContext3D::TEXTURE_2D, mailboxInfo->textureId );
249 context()->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, mailboxInfo ->mailbox.name);
250
251 if (mailboxInfo->size != m_size) {
252 m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_in ternalColorFormat, m_size.width(), m_size.height(), 0, m_colorFormat, GraphicsCo ntext3D::UNSIGNED_BYTE);
253 mailboxInfo->size = m_size;
254 }
255
256 return mailboxInfo.release();
257 }
258
259 PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(unsigned textureId)
260 {
261 RefPtr<MailboxInfo> returnMailbox = adoptRef(new MailboxInfo());
262 context()->genMailboxCHROMIUM(returnMailbox->mailbox.name);
263 returnMailbox->textureId = textureId;
264 returnMailbox->size = m_size;
265 m_textureMailboxes.append(returnMailbox);
266 return returnMailbox.release();
267 }
268
269 void DrawingBuffer::initialize(const IntSize& size)
270 {
271 ASSERT(m_context);
272 m_attributes = m_context->getContextAttributes();
273
274 if (m_attributes.alpha) {
275 m_internalColorFormat = GraphicsContext3D::RGBA;
276 m_colorFormat = GraphicsContext3D::RGBA;
277 m_internalRenderbufferFormat = Extensions3D::RGBA8_OES;
278 } else {
279 m_internalColorFormat = GraphicsContext3D::RGB;
280 m_colorFormat = GraphicsContext3D::RGB;
281 m_internalRenderbufferFormat = Extensions3D::RGB8_OES;
282 }
283
284 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSiz e);
285
286 m_fbo = m_context->createFramebuffer();
287
288 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
289 m_colorBuffer = createColorTexture();
290 m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsCont ext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
291 createSecondaryBuffers();
292 reset(size);
293 m_lastColorBuffer = createNewMailbox(m_colorBuffer);
294 }
295
296 unsigned DrawingBuffer::frontColorBuffer() const
297 {
298 return m_frontColorBuffer;
299 }
300
301 bool DrawingBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3D Object texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool premultiplyAlpha, bool flipY)
302 {
303 if (!m_context || !m_context->makeContextCurrent())
304 return false;
305 if (m_contentsChanged) {
306 if (multisample()) {
307 commit();
308 if (!m_framebufferBinding)
309 bind();
310 else
311 restoreFramebufferBinding();
312 }
313 m_context->flush();
314 }
315 Platform3DObject sourceTexture = colorBuffer();
316
317 if (!context.makeContextCurrent())
318 return false;
319 Extensions3D* extensions = context.extensions();
320 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor ts("GL_CHROMIUM_flipy")
321 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve l))
322 return false;
323
324 bool unpackPremultiplyAlphaNeeded = false;
325 bool unpackUnpremultiplyAlphaNeeded = false;
326 if (m_attributes.alpha && m_attributes.premultipliedAlpha && !premultiplyAlp ha)
327 unpackUnpremultiplyAlphaNeeded = true;
328 else if (m_attributes.alpha && !m_attributes.premultipliedAlpha && premultip lyAlpha)
329 unpackPremultiplyAlphaNeeded = true;
330
331 context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, unpac kUnpremultiplyAlphaNeeded);
332 context.pixelStorei(Extensions3D::UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, unpackP remultiplyAlphaNeeded);
333 context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, flipY);
334 extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, sourceTexture , texture, level, internalFormat, destType);
335 context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false);
336 context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false );
337 context.pixelStorei(Extensions3D::UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, false);
338
339 return true;
340 }
341
342 Platform3DObject DrawingBuffer::framebuffer() const
343 {
344 return m_fbo;
345 }
346
347 blink::WebLayer* DrawingBuffer::platformLayer()
348 {
349 if (!m_context)
350 return 0;
351
352 if (!m_layer) {
353 m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->crea teExternalTextureLayer(this));
354
355 m_layer->setOpaque(!m_attributes.alpha);
356 m_layer->setBlendBackgroundColor(m_attributes.alpha);
357 m_layer->setPremultipliedAlpha(m_attributes.premultipliedAlpha);
358 GraphicsLayer::registerContentsLayer(m_layer->layer());
359 }
360
361 return m_layer->layer();
362 }
363
364 void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer)
365 {
366 if (!m_context || !m_context->makeContextCurrent() || m_context->extensions( )->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR)
367 return;
368
369 Extensions3D* extensions = m_context->extensions();
370
371 if (!imageBuffer)
372 return;
373 Platform3DObject tex = imageBuffer->getBackingTexture();
374 if (tex) {
375 extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontCo lorBuffer,
376 tex, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
377 return;
378 }
379
380 // Since the m_frontColorBuffer was produced and sent to the compositor, it cannot be bound to an fbo.
381 // We have to make a copy of it here and bind that copy instead.
382 // FIXME: That's not true any more, provided we don't change texture
383 // parameters.
384 unsigned sourceTexture = createColorTexture(m_size);
385 extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontColorB uffer, sourceTexture, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BY TE);
386
387 // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding).
388 // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value
389 // rather than querying it off of the context.
390 GC3Dint previousFramebuffer = 0;
391 m_context->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFram ebuffer);
392
393 Platform3DObject framebuffer = m_context->createFramebuffer();
394 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
395 m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsCont ext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, sourceTexture, 0);
396
397 extensions->paintFramebufferToCanvas(framebuffer, size().width(), size().hei ght(), !m_attributes.premultipliedAlpha, imageBuffer);
398 m_context->deleteFramebuffer(framebuffer);
399 m_context->deleteTexture(sourceTexture);
400
401 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuff er);
402 }
403
404 void DrawingBuffer::clearPlatformLayer()
405 {
406 if (m_layer)
407 m_layer->clearTexture();
408
409 if (m_context)
410 m_context->flush();
411 }
412
413 void DrawingBuffer::releaseResources()
414 {
415 if (m_context) {
416 m_context->makeContextCurrent();
417
418 clearPlatformLayer();
419
420 for (size_t i = 0; i < m_textureMailboxes.size(); i++)
421 m_context->deleteTexture(m_textureMailboxes[i]->textureId);
422
423 if (m_multisampleColorBuffer)
424 m_context->deleteRenderbuffer(m_multisampleColorBuffer);
425
426 if (m_depthStencilBuffer)
427 m_context->deleteRenderbuffer(m_depthStencilBuffer);
428
429 if (m_depthBuffer)
430 m_context->deleteRenderbuffer(m_depthBuffer);
431
432 if (m_stencilBuffer)
433 m_context->deleteRenderbuffer(m_stencilBuffer);
434
435 if (m_multisampleFBO)
436 m_context->deleteFramebuffer(m_multisampleFBO);
437
438 if (m_fbo)
439 m_context->deleteFramebuffer(m_fbo);
440
441 m_context.clear();
442 }
443
444 setSize(IntSize());
445
446 m_colorBuffer = 0;
447 m_frontColorBuffer = 0;
448 m_multisampleColorBuffer = 0;
449 m_depthStencilBuffer = 0;
450 m_depthBuffer = 0;
451 m_stencilBuffer = 0;
452 m_multisampleFBO = 0;
453 m_fbo = 0;
454 m_contextEvictionManager.clear();
455
456 m_lastColorBuffer.clear();
457 m_recycledMailboxes.clear();
458 m_textureMailboxes.clear();
459
460 if (m_layer) {
461 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
462 m_layer.clear();
463 }
464 }
465
466 unsigned DrawingBuffer::createColorTexture(const IntSize& size)
467 {
468 if (!m_context)
469 return 0;
470
471 unsigned offscreenColorTexture = m_context->createTexture();
472 if (!offscreenColorTexture)
473 return 0;
474
475 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture) ;
476 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
477 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
478 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
479 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
480 if (!size.isEmpty())
481 m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_in ternalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContex t3D::UNSIGNED_BYTE);
482
483 return offscreenColorTexture;
484 }
485
486 void DrawingBuffer::createSecondaryBuffers()
487 {
488 // create a multisample FBO
489 if (multisample()) {
490 m_multisampleFBO = m_context->createFramebuffer();
491 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisample FBO);
492 m_multisampleColorBuffer = m_context->createRenderbuffer();
493 }
494 }
495
496 bool DrawingBuffer::resizeFramebuffer(const IntSize& size)
497 {
498 // resize regular FBO
499 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
500
501 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer);
502 m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_intern alColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContext3D: :UNSIGNED_BYTE);
503 if (m_lastColorBuffer)
504 m_lastColorBuffer->size = m_size;
505
506 m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsCont ext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
507
508 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
509
510 if (!multisample())
511 resizeDepthStencil(size, 0);
512 if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != Gra phicsContext3D::FRAMEBUFFER_COMPLETE)
513 return false;
514
515 return true;
516 }
517
518 bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size)
519 {
520 if (multisample()) {
521 int maxSampleCount = 0;
522
523 m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount);
524 int sampleCount = std::min(4, maxSampleCount);
525
526 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisample FBO);
527
528 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisamp leColorBuffer);
529 m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3 D::RENDERBUFFER, sampleCount, m_internalRenderbufferFormat, size.width(), size.h eight());
530
531 if (m_context->getError() == GraphicsContext3D::OUT_OF_MEMORY)
532 return false;
533
534 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, Graph icsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleC olorBuffer);
535 resizeDepthStencil(size, sampleCount);
536 if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
537 return false;
538 }
539
540 return true;
541 }
542
543 void DrawingBuffer::resizeDepthStencil(const IntSize& size, int sampleCount)
544 {
545 if (m_attributes.depth && m_attributes.stencil && m_packedDepthStencilExtens ionSupported) {
546 if (!m_depthStencilBuffer)
547 m_depthStencilBuffer = m_context->createRenderbuffer();
548 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthSten cilBuffer);
549 if (multisample())
550 m_context->extensions()->renderbufferStorageMultisample(GraphicsCont ext3D::RENDERBUFFER, sampleCount, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height());
551 else
552 m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, Exte nsions3D::DEPTH24_STENCIL8, size.width(), size.height());
553 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, Graph icsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStenci lBuffer);
554 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, Graph icsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilB uffer);
555 } else {
556 if (m_attributes.depth) {
557 if (!m_depthBuffer)
558 m_depthBuffer = m_context->createRenderbuffer();
559 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depth Buffer);
560 if (multisample())
561 m_context->extensions()->renderbufferStorageMultisample(Graphics Context3D::RENDERBUFFER, sampleCount, GraphicsContext3D::DEPTH_COMPONENT16, size .width(), size.height());
562 else
563 m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, size.width(), size.height());
564 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, G raphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuff er);
565 }
566 if (m_attributes.stencil) {
567 if (!m_stencilBuffer)
568 m_stencilBuffer = m_context->createRenderbuffer();
569 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_stenc ilBuffer);
570 if (multisample())
571 m_context->extensions()->renderbufferStorageMultisample(Graphics Context3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, size.wi dth(), size.height());
572 else
573 m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height());
574 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, G raphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencil Buffer);
575 }
576 }
577 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
578 }
579
580
581
582 void DrawingBuffer::clearFramebuffers(GC3Dbitfield clearMask)
583 {
584 if (!m_context)
585 return;
586
587 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
588
589 m_context->clear(clearMask);
590
591 // The multisample fbo was just cleared, but we also need to clear the non-m ultisampled buffer too.
592 if (m_multisampleFBO) {
593 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
594 m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
595 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisample FBO);
596 }
597 }
598
599 void DrawingBuffer::setSize(const IntSize& size) {
600 if (m_size == size)
601 return;
602
603 s_currentResourceUsePixels += pixelDelta(size);
604 m_size = size;
605 }
606
607 int DrawingBuffer::pixelDelta(const IntSize& size) {
608 return (max(0, size.width()) * max(0, size.height())) - (max(0, m_size.width ()) * max(0, m_size.height()));
609 }
610
611 IntSize DrawingBuffer::adjustSize(const IntSize& size) {
612 IntSize adjustedSize = size;
613
614 // Clamp if the desired size is greater than the maximum texture size for th e device.
615 if (adjustedSize.height() > m_maxTextureSize)
616 adjustedSize.setHeight(m_maxTextureSize);
617
618 if (adjustedSize.width() > m_maxTextureSize)
619 adjustedSize.setWidth(m_maxTextureSize);
620
621 // Try progressively smaller sizes until we find a size that fits or reach a scale limit.
622 int scaleAttempts = 0;
623 while ((s_currentResourceUsePixels + pixelDelta(adjustedSize)) > s_maximumRe sourceUsePixels) {
624 scaleAttempts++;
625 if (scaleAttempts > s_maxScaleAttempts)
626 return IntSize();
627
628 adjustedSize.scale(s_resourceAdjustedRatio);
629
630 if (adjustedSize.isEmpty())
631 return IntSize();
632 }
633
634 return adjustedSize;
635 }
636
637 IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool& evictContext) {
638 IntSize adjustedSize = adjustSize(size);
639 if (!adjustedSize.isEmpty()) {
640 evictContext = false;
641 return adjustedSize; // Buffer fits without evicting a context.
642 }
643
644 // Speculatively adjust the pixel budget to see if the buffer would fit shou ld the oldest context be evicted.
645 IntSize oldestSize = m_contextEvictionManager->oldestContextSize();
646 int pixelDelta = oldestSize.width() * oldestSize.height();
647
648 s_currentResourceUsePixels -= pixelDelta;
649 adjustedSize = adjustSize(size);
650 s_currentResourceUsePixels += pixelDelta;
651
652 evictContext = !adjustedSize.isEmpty();
653 return adjustedSize;
654 }
655
656 void DrawingBuffer::reset(const IntSize& newSize)
657 {
658 if (!m_context)
659 return;
660
661 IntSize adjustedSize;
662 bool evictContext = false;
663 bool isNewContext = m_size.isEmpty();
664 if (s_allowContextEvictionOnCreate && isNewContext)
665 adjustedSize = adjustSizeWithContextEviction(newSize, evictContext);
666 else
667 adjustedSize = adjustSize(newSize);
668
669 if (adjustedSize.isEmpty())
670 return;
671
672 if (evictContext)
673 m_contextEvictionManager->forciblyLoseOldestContext("WARNING: WebGL cont exts have exceeded the maximum allowed backbuffer area. Oldest context will be l ost.");
674
675 if (adjustedSize != m_size) {
676 do {
677 // resize multisample FBO
678 if (!resizeMultisampleFramebuffer(adjustedSize) || !resizeFramebuffe r(adjustedSize)) {
679 adjustedSize.scale(s_resourceAdjustedRatio);
680 continue;
681 }
682 break;
683 } while (!adjustedSize.isEmpty());
684
685 setSize(adjustedSize);
686
687 if (adjustedSize.isEmpty())
688 return;
689 }
690
691 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
692 m_context->clearColor(0, 0, 0, 0);
693 m_context->colorMask(true, true, true, true);
694
695 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
696 if (m_attributes.depth) {
697 m_context->clearDepth(1.0f);
698 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
699 m_context->depthMask(true);
700 }
701 if (m_attributes.stencil) {
702 m_context->clearStencil(0);
703 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
704 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
705 }
706
707 clearFramebuffers(clearMask);
708 }
709
710 void DrawingBuffer::commit(long x, long y, long width, long height)
711 {
712 if (!m_context)
713 return;
714
715 if (width < 0)
716 width = m_size.width();
717 if (height < 0)
718 height = m_size.height();
719
720 m_context->makeContextCurrent();
721
722 if (m_multisampleFBO && !m_contentsChangeCommitted) {
723 m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_multisample FBO);
724 m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_fbo);
725
726 if (m_scissorEnabled)
727 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
728
729 // Use NEAREST, because there is no scale performed during the blit.
730 m_context->extensions()->blitFramebuffer(x, y, width, height, x, y, widt h, height, GraphicsContext3D::COLOR_BUFFER_BIT, GraphicsContext3D::NEAREST);
731
732 if (m_scissorEnabled)
733 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
734 }
735
736 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
737 m_contentsChangeCommitted = true;
738 }
739
740 void DrawingBuffer::restoreFramebufferBinding()
741 {
742 if (!m_context || !m_framebufferBinding)
743 return;
744
745 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBind ing);
746 }
747
748 bool DrawingBuffer::multisample() const
749 {
750 return m_attributes.antialias && m_multisampleExtensionSupported;
751 }
752
753 void DrawingBuffer::bind()
754 {
755 if (!m_context)
756 return;
757
758 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
759 }
760
761 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/platform/graphics/gpu/DrawingBuffer.h ('k') | Source/core/platform/graphics/gpu/DrawingBufferTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698