[chromium] LayerRendererChromium is not getting visibility messages in single threade...
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / LayerRendererChromium.cpp
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
32 #include "config.h"
33
34 #if USE(ACCELERATED_COMPOSITING)
35 #include "LayerRendererChromium.h"
36
37 #include "Extensions3D.h"
38 #include "FloatQuad.h"
39 #include "GeometryBinding.h"
40 #include "GrTexture.h"
41 #include "GraphicsContext3D.h"
42 #include "ManagedTexture.h"
43 #include "NativeImageSkia.h"
44 #include "NotImplemented.h"
45 #include "PlatformColor.h"
46 #include "PlatformContextSkia.h"
47 #include "SharedGraphicsContext3D.h"
48 #include "SkBitmap.h"
49 #include "TextureManager.h"
50 #include "ThrottledTextureUploader.h"
51 #include "TraceEvent.h"
52 #include "TrackingTextureAllocator.h"
53 #include "cc/CCCheckerboardDrawQuad.h"
54 #include "cc/CCDebugBorderDrawQuad.h"
55 #include "cc/CCIOSurfaceDrawQuad.h"
56 #include "cc/CCLayerQuad.h"
57 #include "cc/CCMathUtil.h"
58 #include "cc/CCProxy.h"
59 #include "cc/CCRenderPass.h"
60 #include "cc/CCRenderPassDrawQuad.h"
61 #include "cc/CCRenderSurfaceFilters.h"
62 #include "cc/CCSettings.h"
63 #include "cc/CCSingleThreadProxy.h"
64 #include "cc/CCSolidColorDrawQuad.h"
65 #include "cc/CCStreamVideoDrawQuad.h"
66 #include "cc/CCTextureDrawQuad.h"
67 #include "cc/CCTileDrawQuad.h"
68 #include "cc/CCVideoLayerImpl.h"
69 #include "cc/CCYUVVideoDrawQuad.h"
70 #include <public/WebVideoFrame.h>
71 #include <wtf/CurrentTime.h>
72 #include <wtf/MainThread.h>
73
74 using namespace std;
75 using WebKit::WebTransformationMatrix;
76
77 namespace WebCore {
78
79 namespace {
80
81 static WebTransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
82 {
83     float deltaX = right - left;
84     float deltaY = top - bottom;
85     WebTransformationMatrix ortho;
86     if (!deltaX || !deltaY)
87         return ortho;
88     ortho.setM11(2.0f / deltaX);
89     ortho.setM41(-(right + left) / deltaX);
90     ortho.setM22(2.0f / deltaY);
91     ortho.setM42(-(top + bottom) / deltaY);
92
93     // Z component of vertices is always set to zero as we don't use the depth buffer
94     // while drawing.
95     ortho.setM33(0);
96
97     return ortho;
98 }
99
100 static WebTransformationMatrix screenMatrix(int x, int y, int width, int height)
101 {
102     WebTransformationMatrix screen;
103
104     // Map to viewport.
105     screen.translate3d(x, y, 0);
106     screen.scale3d(width, height, 0);
107
108     // Map x, y and z to unit square.
109     screen.translate3d(0.5, 0.5, 0.5);
110     screen.scale3d(0.5, 0.5, 0.5);
111
112     return screen;
113 }
114
115 bool contextSupportsAcceleratedPainting(GraphicsContext3D* context)
116 {
117     WebCore::Extensions3D* extensions = context->getExtensions();
118     if (extensions->supports("GL_EXT_texture_format_BGRA8888"))
119         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
120     else
121         return false;
122
123     if (extensions->supports("GL_EXT_read_format_bgra"))
124         extensions->ensureEnabled("GL_EXT_read_format_bgra");
125     else
126         return false;
127
128     if (!context->grContext())
129         return false;
130
131     return true;
132 }
133
134 bool needsLionIOSurfaceReadbackWorkaround()
135 {
136 #if OS(DARWIN)
137     static SInt32 systemVersion = 0;
138     if (!systemVersion) {
139         if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr)
140             return false;
141     }
142
143     return systemVersion >= 0x1070;
144 #else
145     return false;
146 #endif
147 }
148
149 class UnthrottledTextureUploader : public TextureUploader {
150     WTF_MAKE_NONCOPYABLE(UnthrottledTextureUploader);
151 public:
152     static PassOwnPtr<UnthrottledTextureUploader> create()
153     {
154         return adoptPtr(new UnthrottledTextureUploader());
155     }
156     virtual ~UnthrottledTextureUploader() { }
157
158     virtual bool isBusy() { return false; }
159     virtual void beginUploads() { }
160     virtual void endUploads() { }
161     virtual void uploadTexture(CCGraphicsContext* context, LayerTextureUpdater::Texture* texture, TextureAllocator* allocator, const IntRect sourceRect, const IntRect destRect) { texture->updateRect(context, allocator, sourceRect, destRect); }
162
163 protected:
164     UnthrottledTextureUploader() { }
165 };
166
167 } // anonymous namespace
168
169 class LayerRendererSwapBuffersCompleteCallbackAdapter : public Extensions3DChromium::SwapBuffersCompleteCallbackCHROMIUM {
170 public:
171     static PassOwnPtr<LayerRendererSwapBuffersCompleteCallbackAdapter> create(LayerRendererChromium* layerRenderer)
172     {
173         return adoptPtr(new LayerRendererSwapBuffersCompleteCallbackAdapter(layerRenderer));
174     }
175     virtual ~LayerRendererSwapBuffersCompleteCallbackAdapter() { }
176
177     virtual void onSwapBuffersComplete()
178     {
179         m_layerRenderer->onSwapBuffersComplete();
180     }
181
182 private:
183     explicit LayerRendererSwapBuffersCompleteCallbackAdapter(LayerRendererChromium* layerRenderer)
184     {
185         m_layerRenderer = layerRenderer;
186     }
187
188     LayerRendererChromium* m_layerRenderer;
189 };
190
191 class LayerRendererGpuMemoryAllocationChangedCallbackAdapter : public Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM {
192 public:
193     static PassOwnPtr<LayerRendererGpuMemoryAllocationChangedCallbackAdapter> create(LayerRendererChromium* layerRenderer)
194     {
195         return adoptPtr(new LayerRendererGpuMemoryAllocationChangedCallbackAdapter(layerRenderer));
196     }
197     virtual ~LayerRendererGpuMemoryAllocationChangedCallbackAdapter() { }
198
199     virtual void onGpuMemoryAllocationChanged(Extensions3DChromium::GpuMemoryAllocationCHROMIUM allocation)
200     {
201         // FIXME: This is called on the main thread in single threaded mode, but we expect it on the impl thread.
202         if (m_bindToImplThread) {
203           ASSERT(CCProxy::isMainThread());
204           DebugScopedSetImplThread impl;
205           onGpuMemoryAllocationChangedOnImpl(allocation);
206         } else {
207           ASSERT(CCProxy::isImplThread());
208           onGpuMemoryAllocationChangedOnImpl(allocation);
209         }
210     }
211
212 private:
213     explicit LayerRendererGpuMemoryAllocationChangedCallbackAdapter(LayerRendererChromium* layerRenderer)
214         : m_layerRenderer(layerRenderer), m_bindToImplThread(!CCProxy::hasImplThread())
215     {
216     }
217
218     void onGpuMemoryAllocationChangedOnImpl(Extensions3DChromium::GpuMemoryAllocationCHROMIUM allocation)
219     {
220         ASSERT(CCProxy::isImplThread());
221         m_layerRenderer->setGpuMemoryAllocation(allocation);
222     }
223
224     LayerRendererChromium* m_layerRenderer;
225     bool m_bindToImplThread;
226 };
227
228 PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(CCRendererClient* client, PassRefPtr<GraphicsContext3D> context, TextureUploaderOption textureUploaderSetting)
229 {
230     OwnPtr<LayerRendererChromium> layerRenderer(adoptPtr(new LayerRendererChromium(client, context, textureUploaderSetting)));
231     if (!layerRenderer->initialize())
232         return nullptr;
233
234     return layerRenderer.release();
235 }
236
237 LayerRendererChromium::LayerRendererChromium(CCRendererClient* client,
238                                              PassRefPtr<GraphicsContext3D> context,
239                                              TextureUploaderOption textureUploaderSetting)
240     : CCRenderer(client)
241     , m_currentRenderPass(0)
242     , m_currentManagedTexture(0)
243     , m_offscreenFramebufferId(0)
244     , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
245     , m_context(context)
246     , m_defaultRenderPass(0)
247     , m_isViewportChanged(false)
248     , m_isFramebufferDiscarded(false)
249     , m_visible(true)
250     , m_textureUploaderSetting(textureUploaderSetting)
251 {
252     ASSERT(m_context.get());
253 }
254
255 class ContextLostCallbackAdapter : public GraphicsContext3D::ContextLostCallback {
256 public:
257     static PassOwnPtr<ContextLostCallbackAdapter> create(CCRendererClient* client)
258     {
259         return adoptPtr(new ContextLostCallbackAdapter(client));
260     }
261
262     virtual void onContextLost()
263     {
264         m_client->didLoseContext();
265     }
266
267 private:
268     explicit ContextLostCallbackAdapter(CCRendererClient* client)
269         : m_client(client) { }
270
271     CCRendererClient* m_client;
272 };
273
274 bool LayerRendererChromium::initialize()
275 {
276     if (!m_context->makeContextCurrent())
277         return false;
278
279     m_context->setContextLostCallback(ContextLostCallbackAdapter::create(m_client));
280
281     if (settings().acceleratePainting && contextSupportsAcceleratedPainting(m_context.get()))
282         m_capabilities.usingAcceleratedPainting = true;
283
284     WebCore::Extensions3D* extensions = m_context->getExtensions();
285     m_capabilities.contextHasCachedFrontBuffer = extensions->supports("GL_CHROMIUM_front_buffer_cached");
286     if (m_capabilities.contextHasCachedFrontBuffer)
287         extensions->ensureEnabled("GL_CHROMIUM_front_buffer_cached");
288
289     m_capabilities.usingPartialSwap = CCSettings::partialSwapEnabled() && extensions->supports("GL_CHROMIUM_post_sub_buffer");
290     if (m_capabilities.usingPartialSwap)
291         extensions->ensureEnabled("GL_CHROMIUM_post_sub_buffer");
292
293     m_capabilities.usingMapSub = extensions->supports("GL_CHROMIUM_map_sub");
294     if (m_capabilities.usingMapSub)
295         extensions->ensureEnabled("GL_CHROMIUM_map_sub");
296
297     // Use the swapBuffers callback only with the threaded proxy.
298     if (CCProxy::hasImplThread())
299         m_capabilities.usingSwapCompleteCallback = extensions->supports("GL_CHROMIUM_swapbuffers_complete_callback");
300     if (m_capabilities.usingSwapCompleteCallback) {
301         extensions->ensureEnabled("GL_CHROMIUM_swapbuffers_complete_callback");
302         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
303         extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(LayerRendererSwapBuffersCompleteCallbackAdapter::create(this));
304     }
305
306     if (extensions->supports("GL_EXT_texture_format_BGRA8888"))
307         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
308
309     m_capabilities.usingSetVisibility = extensions->supports("GL_CHROMIUM_set_visibility");
310     if (m_capabilities.usingSetVisibility)
311         extensions->ensureEnabled("GL_CHROMIUM_set_visibility");
312
313     if (extensions->supports("GL_CHROMIUM_iosurface")) {
314         ASSERT(extensions->supports("GL_ARB_texture_rectangle"));
315         extensions->ensureEnabled("GL_ARB_texture_rectangle");
316         extensions->ensureEnabled("GL_CHROMIUM_iosurface");
317     }
318
319     m_capabilities.usingTextureUsageHint = extensions->supports("GL_ANGLE_texture_usage");
320     if (m_capabilities.usingTextureUsageHint)
321         extensions->ensureEnabled("GL_ANGLE_texture_usage");
322
323     m_capabilities.usingTextureStorageExtension = extensions->supports("GL_EXT_texture_storage");
324     if (m_capabilities.usingTextureStorageExtension)
325         extensions->ensureEnabled("GL_EXT_texture_storage");
326
327     m_capabilities.usingGpuMemoryManager = extensions->supports("GL_CHROMIUM_gpu_memory_manager");
328     if (m_capabilities.usingGpuMemoryManager) {
329         extensions->ensureEnabled("GL_CHROMIUM_gpu_memory_manager");
330         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
331         extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(LayerRendererGpuMemoryAllocationChangedCallbackAdapter::create(this));
332     } else {
333         m_client->setMemoryAllocationLimitBytes(TextureManager::highLimitBytes(viewportSize()));
334     }
335
336     m_capabilities.usingDiscardFramebuffer = extensions->supports("GL_CHROMIUM_discard_framebuffer");
337     if (m_capabilities.usingDiscardFramebuffer)
338         extensions->ensureEnabled("GL_CHROMIUM_discard_framebuffer");
339
340     GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
341     m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get());
342
343     if (!initializeSharedObjects())
344         return false;
345
346     // Make sure the viewport and context gets initialized, even if it is to zero.
347     viewportChanged();
348     return true;
349 }
350
351 LayerRendererChromium::~LayerRendererChromium()
352 {
353     ASSERT(CCProxy::isImplThread());
354     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
355     extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(nullptr);
356     extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(nullptr);
357     cleanupSharedObjects();
358 }
359
360 GraphicsContext3D* LayerRendererChromium::context()
361 {
362     return m_context.get();
363 }
364
365 void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line)
366 {
367     unsigned long error = context->getError();
368     if (error != GraphicsContext3D::NO_ERROR)
369         LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
370 }
371
372 void LayerRendererChromium::setVisible(bool visible)
373 {
374     if (m_visible == visible)
375         return;
376     m_visible = visible;
377
378     // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers
379     // crbug.com/116049
380     if (m_capabilities.usingSetVisibility) {
381         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
382         extensions3DChromium->setVisibilityCHROMIUM(visible);
383     }
384 }
385
386 void LayerRendererChromium::releaseRenderPassTextures()
387 {
388     if (m_implTextureManager)
389         m_implTextureManager->evictAndDeleteAllTextures(m_implTextureAllocator.get());
390 }
391
392 void LayerRendererChromium::viewportChanged()
393 {
394     m_isViewportChanged = true;
395
396     // Reset the current RenderPass to force an update of the viewport and
397     // projection matrix next time useRenderPass is called.
398     m_currentRenderPass = 0;
399 }
400
401 void LayerRendererChromium::clearRenderPass(const CCRenderPass* renderPass, const FloatRect& framebufferDamageRect)
402 {
403     // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen. If we
404     // are using partial swap / scissor optimization, then the surface should only
405     // clear the damaged region, so that we don't accidentally clear un-changed portions
406     // of the screen.
407
408     if (renderPass->hasTransparentBackground())
409         GLC(m_context, m_context->clearColor(0, 0, 0, 0));
410     else
411         GLC(m_context, m_context->clearColor(0, 0, 1, 1));
412
413     if (m_capabilities.usingPartialSwap)
414         setScissorToRect(enclosingIntRect(framebufferDamageRect));
415     else
416         GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
417
418 #if defined(NDEBUG)
419     if (renderPass->hasTransparentBackground())
420 #endif
421         m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
422
423     GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
424 }
425
426
427 void LayerRendererChromium::decideRenderPassAllocationsForFrame(const CCRenderPassList& renderPassesInDrawOrder)
428 {
429     // FIXME: Get this memory limit from GPU Memory Manager
430     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
431     size_t maxLimitBytes = TextureManager::highLimitBytes(viewportSize());
432     size_t memoryLimitBytes = maxLimitBytes - contentsMemoryUseBytes > 0u ? maxLimitBytes - contentsMemoryUseBytes : 0u;
433
434     m_implTextureManager->setMaxMemoryLimitBytes(memoryLimitBytes);
435 }
436
437 void LayerRendererChromium::beginDrawingFrame(const CCRenderPass* rootRenderPass)
438 {
439     // FIXME: Remove this once framebuffer is automatically recreated on first use
440     ensureFramebuffer();
441
442     m_defaultRenderPass = rootRenderPass;
443     ASSERT(m_defaultRenderPass);
444
445     if (viewportSize().isEmpty())
446         return;
447
448     TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
449     if (m_isViewportChanged) {
450         // Only reshape when we know we are going to draw. Otherwise, the reshape
451         // can leave the window at the wrong size if we never draw and the proper
452         // viewport size is never set.
453         m_isViewportChanged = false;
454         m_context->reshape(viewportWidth(), viewportHeight());
455     }
456
457     makeContextCurrent();
458     // Bind the common vertex attributes used for drawing all the layers.
459     m_sharedGeometry->prepareForDraw();
460
461     GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST));
462     GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
463     GLC(m_context, m_context->colorMask(true, true, true, true));
464     GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
465     GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
466 }
467
468 void LayerRendererChromium::doNoOp()
469 {
470     GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
471     GLC(m_context, m_context->flush());
472 }
473
474 void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass, const FloatRect& framebufferDamageRect)
475 {
476     if (!useRenderPass(renderPass))
477         return;
478
479     clearRenderPass(renderPass, framebufferDamageRect);
480
481     const CCQuadList& quadList = renderPass->quadList();
482     for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it)
483         drawQuad(it->get());
484 }
485
486 void LayerRendererChromium::drawQuad(const CCDrawQuad* quad)
487 {
488     IntRect scissorRect = quad->scissorRect();
489
490     ASSERT(!scissorRect.isEmpty());
491     if (scissorRect.isEmpty())
492         return;
493
494     setScissorToRect(scissorRect);
495
496     if (quad->needsBlending())
497         GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
498     else
499         GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
500
501     switch (quad->material()) {
502     case CCDrawQuad::Invalid:
503         ASSERT_NOT_REACHED();
504         break;
505     case CCDrawQuad::Checkerboard:
506         drawCheckerboardQuad(quad->toCheckerboardDrawQuad());
507         break;
508     case CCDrawQuad::DebugBorder:
509         drawDebugBorderQuad(quad->toDebugBorderDrawQuad());
510         break;
511     case CCDrawQuad::IOSurfaceContent:
512         drawIOSurfaceQuad(quad->toIOSurfaceDrawQuad());
513         break;
514     case CCDrawQuad::RenderPass:
515         drawRenderPassQuad(quad->toRenderPassDrawQuad());
516         break;
517     case CCDrawQuad::SolidColor:
518         drawSolidColorQuad(quad->toSolidColorDrawQuad());
519         break;
520     case CCDrawQuad::StreamVideoContent:
521         drawStreamVideoQuad(quad->toStreamVideoDrawQuad());
522         break;
523     case CCDrawQuad::TextureContent:
524         drawTextureQuad(quad->toTextureDrawQuad());
525         break;
526     case CCDrawQuad::TiledContent:
527         drawTileQuad(quad->toTileDrawQuad());
528         break;
529     case CCDrawQuad::YUVVideoContent:
530         drawYUVVideoQuad(quad->toYUVVideoDrawQuad());
531         break;
532     }
533 }
534
535 void LayerRendererChromium::drawCheckerboardQuad(const CCCheckerboardDrawQuad* quad)
536 {
537     const TileCheckerboardProgram* program = tileCheckerboardProgram();
538     ASSERT(program && program->initialized());
539     GLC(context(), context()->useProgram(program->program()));
540
541     IntRect tileRect = quad->quadRect();
542     WebTransformationMatrix tileTransform = quad->quadTransform();
543     tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
544
545     float texOffsetX = tileRect.x();
546     float texOffsetY = tileRect.y();
547     float texScaleX = tileRect.width();
548     float texScaleY = tileRect.height();
549     GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLocation(), texOffsetX, texOffsetY, texScaleX, texScaleY));
550
551     const int checkerboardWidth = 16;
552     float frequency = 1.0 / checkerboardWidth;
553
554     GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocation(), frequency));
555
556     float opacity = quad->opacity();
557     drawTexturedQuad(tileTransform,
558                      tileRect.width(), tileRect.height(), opacity, FloatQuad(),
559                      program->vertexShader().matrixLocation(),
560                      program->fragmentShader().alphaLocation(), -1);
561 }
562
563 void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* quad)
564 {
565     static float glMatrix[16];
566     const SolidColorProgram* program = solidColorProgram();
567     ASSERT(program && program->initialized());
568     GLC(context(), context()->useProgram(program->program()));
569
570     const IntRect& layerRect = quad->quadRect();
571     WebTransformationMatrix renderMatrix = quad->quadTransform();
572     renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y());
573     renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height());
574     LayerRendererChromium::toGLMatrix(&glMatrix[0], projectionMatrix() * renderMatrix);
575     GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0]));
576
577     const Color& color = quad->color();
578     float alpha = color.alpha() / 255.0;
579
580     GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (color.red() / 255.0) * alpha, (color.green() / 255.0) * alpha, (color.blue() / 255.0) * alpha, alpha));
581
582     GLC(context(), context()->lineWidth(quad->width()));
583
584     // The indices for the line are stored in the same array as the triangle indices.
585     GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
586 }
587
588 static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const WebKit::WebFilterOperations& filters, ManagedTexture* sourceTexture)
589 {
590     if (filters.isEmpty())
591         return SkBitmap();
592
593     RefPtr<GraphicsContext3D> filterContext = CCProxy::hasImplThread() ? SharedGraphicsContext3D::getForImplThread() : SharedGraphicsContext3D::get();
594     if (!filterContext)
595         return SkBitmap();
596
597     layerRenderer->context()->flush();
598
599     return CCRenderSurfaceFilters::apply(filters, sourceTexture->textureId(), sourceTexture->size(), filterContext.get());
600 }
601
602 void LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* quad, const WebTransformationMatrix& contentsDeviceTransform)
603 {
604     // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background.
605     // The algorithm works as follows:
606     // 1. Compute a bounding box around the pixels that will be visible through the quad.
607     // 2. Read the pixels in the bounding box into a buffer R.
608     // 3. Apply the background filter to R, so that it is applied in the pixels' coordinate space.
609     // 4. Apply the quad's inverse transform to map the pixels in R into the quad's content space. This implicitly
610     // clips R by the content bounds of the quad since the destination texture has bounds matching the quad's content.
611     // 5. Draw the background texture for the contents using the same transform as used to draw the contents itself. This is done
612     // without blending to replace the current background pixels with the new filtered background.
613     // 6. Draw the contents of the quad over drop of the new background with blending, as per usual. The filtered background
614     // pixels will show through any non-opaque pixels in this draws.
615     //
616     // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
617
618     CCRenderSurface* drawingSurface = quad->renderPass()->targetSurface();
619     if (quad->backgroundFilters().isEmpty())
620         return;
621
622     // FIXME: We only allow background filters on an opaque render surface because other surfaces may contain
623     // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied.
624     if (m_currentRenderPass->hasTransparentBackground())
625         return;
626     ASSERT(!m_currentManagedTexture);
627
628     // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused).
629     IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().boundingBox()));
630
631     int top, right, bottom, left;
632     quad->backgroundFilters().getOutsets(top, right, bottom, left);
633     deviceRect.move(-left, -top);
634     deviceRect.expand(left + right, top + bottom);
635
636     deviceRect.intersect(m_currentRenderPass->framebufferOutputRect());
637
638     OwnPtr<ManagedTexture> deviceBackgroundTexture = ManagedTexture::create(m_implTextureManager.get());
639     if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
640         return;
641
642     SkBitmap filteredDeviceBackground = applyFilters(this, quad->backgroundFilters(), deviceBackgroundTexture.get());
643     if (!filteredDeviceBackground.getTexture())
644         return;
645
646     GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.getTexture());
647     int filteredDeviceBackgroundTextureId = texture->getTextureHandle();
648
649     if (!drawingSurface->prepareBackgroundTexture(this))
650         return;
651
652     const CCRenderPass* targetRenderPass = m_currentRenderPass;
653     if (useManagedTexture(drawingSurface->backgroundTexture(), quad->quadRect())) {
654         // Copy the readback pixels from device to the background texture for the surface.
655         WebTransformationMatrix deviceToFramebufferTransform;
656         deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0);
657         deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1);
658         deviceToFramebufferTransform.multiply(contentsDeviceTransform.inverse());
659         deviceToFramebufferTransform.translate(deviceRect.width() / 2.0, deviceRect.height() / 2.0);
660         deviceToFramebufferTransform.translate(deviceRect.x(), deviceRect.y());
661
662         copyTextureToFramebuffer(filteredDeviceBackgroundTextureId, deviceRect.size(), deviceToFramebufferTransform);
663
664         useRenderPass(targetRenderPass);
665     }
666 }
667
668 void LayerRendererChromium::drawRenderPassQuad(const CCRenderPassDrawQuad* quad)
669 {
670     // The replica is always drawn first, so free after drawing the contents.
671     bool shouldReleaseTextures = !quad->isReplica();
672
673     CCRenderSurface* drawingSurface = quad->renderPass()->targetSurface();
674
675     WebTransformationMatrix renderTransform = quad->layerTransform();
676     // Apply a scaling factor to size the quad from 1x1 to its intended size.
677     renderTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1);
678     WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(windowMatrix() * projectionMatrix() * renderTransform).to2dTransform();
679
680     // Can only draw surface if device matrix is invertible.
681     if (!contentsDeviceTransform.isInvertible() || !drawingSurface->hasValidContentsTexture()) {
682         if (shouldReleaseTextures) {
683             drawingSurface->releaseBackgroundTexture();
684             drawingSurface->releaseContentsTexture();
685         }
686         return;
687     }
688
689     drawBackgroundFilters(quad, contentsDeviceTransform);
690
691     // FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
692     // Apply filters to the contents texture.
693     SkBitmap filterBitmap = applyFilters(this, quad->filters(), drawingSurface->contentsTexture());
694     int contentsTextureId = drawingSurface->contentsTexture()->textureId();
695     if (filterBitmap.getTexture()) {
696         GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
697         contentsTextureId = texture->getTextureHandle();
698     }
699
700     // Draw the background texture if there is one.
701     if (drawingSurface->hasValidBackgroundTexture())
702         copyTextureToFramebuffer(drawingSurface->backgroundTexture()->textureId(), quad->quadRect().size(), quad->layerTransform());
703
704     FloatQuad deviceQuad = contentsDeviceTransform.mapQuad(sharedGeometryQuad());
705     CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox()));
706     CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad);
707
708     // Use anti-aliasing programs only when necessary.
709     bool useAA = (!deviceQuad.isRectilinear() || !deviceQuad.boundingBox().isExpressibleAsIntRect());
710     if (useAA) {
711         deviceLayerBounds.inflateAntiAliasingDistance();
712         deviceLayerEdges.inflateAntiAliasingDistance();
713     }
714
715     bool useMask = quad->maskTextureId();
716
717     // FIXME: use the backgroundTexture and blend the background in with this draw instead of having a separate copy of the background texture.
718
719     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
720     context()->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId);
721
722     int shaderQuadLocation = -1;
723     int shaderEdgeLocation = -1;
724     int shaderMaskSamplerLocation = -1;
725     int shaderMatrixLocation = -1;
726     int shaderAlphaLocation = -1;
727     if (useAA && useMask) {
728         const RenderPassMaskProgramAA* program = renderPassMaskProgramAA();
729         GLC(context(), context()->useProgram(program->program()));
730         GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
731
732         shaderQuadLocation = program->vertexShader().pointLocation();
733         shaderEdgeLocation = program->fragmentShader().edgeLocation();
734         shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
735         shaderMatrixLocation = program->vertexShader().matrixLocation();
736         shaderAlphaLocation = program->fragmentShader().alphaLocation();
737     } else if (!useAA && useMask) {
738         const RenderPassMaskProgram* program = renderPassMaskProgram();
739         GLC(context(), context()->useProgram(program->program()));
740         GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
741
742         shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
743         shaderMatrixLocation = program->vertexShader().matrixLocation();
744         shaderAlphaLocation = program->fragmentShader().alphaLocation();
745     } else if (useAA && !useMask) {
746         const RenderPassProgramAA* program = renderPassProgramAA();
747         GLC(context(), context()->useProgram(program->program()));
748         GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
749
750         shaderQuadLocation = program->vertexShader().pointLocation();
751         shaderEdgeLocation = program->fragmentShader().edgeLocation();
752         shaderMatrixLocation = program->vertexShader().matrixLocation();
753         shaderAlphaLocation = program->fragmentShader().alphaLocation();
754     } else {
755         const RenderPassProgram* program = renderPassProgram();
756         GLC(context(), context()->useProgram(program->program()));
757         GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
758
759         shaderMatrixLocation = program->vertexShader().matrixLocation();
760         shaderAlphaLocation = program->fragmentShader().alphaLocation();
761     }
762
763     if (shaderMaskSamplerLocation != -1) {
764         GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
765         GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1));
766         context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->maskTextureId());
767         GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
768     }
769
770     if (shaderEdgeLocation != -1) {
771         float edge[24];
772         deviceLayerEdges.toFloatArray(edge);
773         deviceLayerBounds.toFloatArray(&edge[12]);
774         GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge));
775     }
776
777     // Map device space quad to surface space.
778     FloatQuad surfaceQuad = contentsDeviceTransform.inverse().mapQuad(deviceLayerEdges.floatQuad());
779
780     drawTexturedQuad(quad->layerTransform(), quad->quadRect().width(), quad->quadRect().height(), quad->opacity(), surfaceQuad,
781                      shaderMatrixLocation, shaderAlphaLocation, shaderQuadLocation);
782
783     if (shouldReleaseTextures) {
784         drawingSurface->releaseBackgroundTexture();
785         drawingSurface->releaseContentsTexture();
786     }
787 }
788
789 void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad)
790 {
791     const SolidColorProgram* program = solidColorProgram();
792     GLC(context(), context()->useProgram(program->program()));
793
794     IntRect tileRect = quad->quadRect();
795
796     WebTransformationMatrix tileTransform = quad->quadTransform();
797     tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
798
799     const Color& color = quad->color();
800     float opacity = quad->opacity();
801     float alpha = (color.alpha() / 255.0) * opacity;
802
803     GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (color.red() / 255.0) * alpha, (color.green() / 255.0) * alpha, (color.blue() / 255.0) * alpha, alpha));
804
805     drawTexturedQuad(tileTransform,
806                      tileRect.width(), tileRect.height(), 1.0, FloatQuad(),
807                      program->vertexShader().matrixLocation(),
808                      -1, -1);
809 }
810
811 struct TileProgramUniforms {
812     unsigned program;
813     unsigned samplerLocation;
814     unsigned vertexTexTransformLocation;
815     unsigned fragmentTexTransformLocation;
816     unsigned edgeLocation;
817     unsigned matrixLocation;
818     unsigned alphaLocation;
819     unsigned pointLocation;
820 };
821
822 template<class T>
823 static void tileUniformLocation(T program, TileProgramUniforms& uniforms)
824 {
825     uniforms.program = program->program();
826     uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTransformLocation();
827     uniforms.matrixLocation = program->vertexShader().matrixLocation();
828     uniforms.pointLocation = program->vertexShader().pointLocation();
829
830     uniforms.samplerLocation = program->fragmentShader().samplerLocation();
831     uniforms.alphaLocation = program->fragmentShader().alphaLocation();
832     uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTexTransformLocation();
833     uniforms.edgeLocation = program->fragmentShader().edgeLocation();
834 }
835
836 void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
837 {
838     const IntRect& tileRect = quad->quadVisibleRect();
839
840     FloatRect clampRect(tileRect);
841     // Clamp texture coordinates to avoid sampling outside the layer
842     // by deflating the tile region half a texel or half a texel
843     // minus epsilon for one pixel layers. The resulting clamp region
844     // is mapped to the unit square by the vertex shader and mapped
845     // back to normalized texture coordinates by the fragment shader
846     // after being clamped to 0-1 range.
847     const float epsilon = 1 / 1024.0f;
848     float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
849     float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
850     clampRect.inflateX(-clampX);
851     clampRect.inflateY(-clampY);
852     FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
853
854     FloatPoint textureOffset = quad->textureOffset() + clampOffset +
855                                IntPoint(quad->quadVisibleRect().location() - quad->quadRect().location());
856
857     // Map clamping rectangle to unit square.
858     float vertexTexTranslateX = -clampRect.x() / clampRect.width();
859     float vertexTexTranslateY = -clampRect.y() / clampRect.height();
860     float vertexTexScaleX = tileRect.width() / clampRect.width();
861     float vertexTexScaleY = tileRect.height() / clampRect.height();
862
863     // Map to normalized texture coordinates.
864     const IntSize& textureSize = quad->textureSize();
865     float fragmentTexTranslateX = textureOffset.x() / textureSize.width();
866     float fragmentTexTranslateY = textureOffset.y() / textureSize.height();
867     float fragmentTexScaleX = clampRect.width() / textureSize.width();
868     float fragmentTexScaleY = clampRect.height() / textureSize.height();
869
870
871     FloatQuad localQuad;
872     WebTransformationMatrix deviceTransform = WebTransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
873     if (!deviceTransform.isInvertible())
874         return;
875
876     bool clipped = false;
877     FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->layerRect()), clipped);
878
879     TileProgramUniforms uniforms;
880     // For now, we simply skip anti-aliasing with the quad is clipped. This only happens
881     // on perspective transformed layers that go partially behind the camera.
882     if (quad->isAntialiased() && !clipped) {
883         if (quad->swizzleContents())
884             tileUniformLocation(tileProgramSwizzleAA(), uniforms);
885         else
886             tileUniformLocation(tileProgramAA(), uniforms);
887     } else {
888         if (quad->needsBlending()) {
889             if (quad->swizzleContents())
890                 tileUniformLocation(tileProgramSwizzle(), uniforms);
891             else
892                 tileUniformLocation(tileProgram(), uniforms);
893         } else {
894             if (quad->swizzleContents())
895                 tileUniformLocation(tileProgramSwizzleOpaque(), uniforms);
896             else
897                 tileUniformLocation(tileProgramOpaque(), uniforms);
898         }
899     }
900
901     GLC(context(), context()->useProgram(uniforms.program));
902     GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
903     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
904     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
905     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter()));
906     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter()));
907
908
909     if (!clipped && quad->isAntialiased()) {
910
911         CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox()));
912         deviceLayerBounds.inflateAntiAliasingDistance();
913
914         CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad);
915         deviceLayerEdges.inflateAntiAliasingDistance();
916
917         float edge[24];
918         deviceLayerEdges.toFloatArray(edge);
919         deviceLayerBounds.toFloatArray(&edge[12]);
920         GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
921
922         GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
923         GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
924
925         FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY());
926         FloatPoint bottomLeft(tileRect.x(), tileRect.maxY());
927         FloatPoint topLeft(tileRect.x(), tileRect.y());
928         FloatPoint topRight(tileRect.maxX(), tileRect.y());
929
930         // Map points to device space.
931         bottomRight = deviceTransform.mapPoint(bottomRight);
932         bottomLeft = deviceTransform.mapPoint(bottomLeft);
933         topLeft = deviceTransform.mapPoint(topLeft);
934         topRight = deviceTransform.mapPoint(topRight);
935
936         CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
937         CCLayerQuad::Edge leftEdge(bottomLeft, topLeft);
938         CCLayerQuad::Edge topEdge(topLeft, topRight);
939         CCLayerQuad::Edge rightEdge(topRight, bottomRight);
940
941         // Only apply anti-aliasing to edges not clipped during culling.
942         if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
943             topEdge = deviceLayerEdges.top();
944         if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
945             leftEdge = deviceLayerEdges.left();
946         if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX())
947             rightEdge = deviceLayerEdges.right();
948         if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY())
949             bottomEdge = deviceLayerEdges.bottom();
950
951         float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
952         bottomEdge.scale(sign);
953         leftEdge.scale(sign);
954         topEdge.scale(sign);
955         rightEdge.scale(sign);
956
957         // Create device space quad.
958         CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
959
960         // Map quad to layer space.
961         WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse();
962         localQuad = inverseDeviceTransform.mapQuad(deviceQuad.floatQuad());
963     } else {
964         // Move fragment shader transform to vertex shader. We can do this while
965         // still producing correct results as fragmentTexTransformLocation
966         // should always be non-negative when tiles are transformed in a way
967         // that could result in sampling outside the layer.
968         vertexTexScaleX *= fragmentTexScaleX;
969         vertexTexScaleY *= fragmentTexScaleY;
970         vertexTexTranslateX *= fragmentTexScaleX;
971         vertexTexTranslateY *= fragmentTexScaleY;
972         vertexTexTranslateX += fragmentTexTranslateX;
973         vertexTexTranslateY += fragmentTexTranslateY;
974
975         GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
976
977         localQuad = FloatRect(tileRect);
978     }
979
980     // Normalize to tileRect.
981     localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
982
983     drawTexturedQuad(quad->quadTransform(), tileRect.width(), tileRect.height(), quad->opacity(), localQuad, uniforms.matrixLocation, uniforms.alphaLocation, uniforms.pointLocation);
984 }
985
986 void LayerRendererChromium::drawYUVVideoQuad(const CCYUVVideoDrawQuad* quad)
987 {
988     const VideoYUVProgram* program = videoYUVProgram();
989     ASSERT(program && program->initialized());
990
991     const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane();
992     const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane();
993     const CCVideoLayerImpl::FramePlane& vPlane = quad->vPlane();
994
995     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
996     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yPlane.textureId));
997     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2));
998     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uPlane.textureId));
999     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3));
1000     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vPlane.textureId));
1001
1002     GLC(context(), context()->useProgram(program->program()));
1003
1004     float yWidthScaleFactor = static_cast<float>(yPlane.visibleSize.width()) / yPlane.size.width();
1005     // Arbitrarily take the u sizes because u and v dimensions are identical.
1006     float uvWidthScaleFactor = static_cast<float>(uPlane.visibleSize.width()) / uPlane.size.width();
1007     GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
1008     GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
1009
1010     GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
1011     GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2));
1012     GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3));
1013
1014     // These values are magic numbers that are used in the transformation from YUV to RGB color values.
1015     // They are taken from the following webpage: http://www.fourcc.org/fccyvrgb.php
1016     float yuv2RGB[9] = {
1017         1.164f, 1.164f, 1.164f,
1018         0.f, -.391f, 2.018f,
1019         1.596f, -.813f, 0.f,
1020     };
1021     GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 1, 0, yuv2RGB));
1022
1023     // These values map to 16, 128, and 128 respectively, and are computed
1024     // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
1025     // They are used in the YUV to RGBA conversion formula:
1026     //   Y - 16   : Gives 16 values of head and footroom for overshooting
1027     //   U - 128  : Turns unsigned U into signed U [-128,127]
1028     //   V - 128  : Turns unsigned V into signed V [-128,127]
1029     float yuvAdjust[3] = {
1030         -0.0625f,
1031         -0.5f,
1032         -0.5f,
1033     };
1034     GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, yuvAdjust));
1035
1036     const IntSize& bounds = quad->quadRect().size();
1037     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), FloatQuad(),
1038                                     program->vertexShader().matrixLocation(),
1039                                     program->fragmentShader().alphaLocation(),
1040                                     -1);
1041
1042     // Reset active texture back to texture 0.
1043     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1044 }
1045
1046 void LayerRendererChromium::drawStreamVideoQuad(const CCStreamVideoDrawQuad* quad)
1047 {
1048     static float glMatrix[16];
1049
1050     ASSERT(context()->getExtensions()->supports("GL_OES_EGL_image_external") && context()->getExtensions()->isEnabled("GL_OES_EGL_image_external"));
1051
1052     const VideoStreamTextureProgram* program = videoStreamTextureProgram();
1053     GLC(context(), context()->useProgram(program->program()));
1054
1055     toGLMatrix(&glMatrix[0], quad->matrix());
1056     GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, glMatrix));
1057
1058     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1059     GLC(context(), context()->bindTexture(Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES, quad->textureId()));
1060
1061     GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
1062
1063     const IntSize& bounds = quad->quadRect().size();
1064     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
1065                      program->vertexShader().matrixLocation(),
1066                      program->fragmentShader().alphaLocation(),
1067                      -1);
1068 }
1069
1070 struct TextureProgramBinding {
1071     template<class Program> void set(Program* program)
1072     {
1073         ASSERT(program && program->initialized());
1074         programId = program->program();
1075         samplerLocation = program->fragmentShader().samplerLocation();
1076         matrixLocation = program->vertexShader().matrixLocation();
1077         alphaLocation = program->fragmentShader().alphaLocation();
1078     }
1079     int programId;
1080     int samplerLocation;
1081     int matrixLocation;
1082     int alphaLocation;
1083 };
1084
1085 struct TexTransformTextureProgramBinding : TextureProgramBinding {
1086     template<class Program> void set(Program* program)
1087     {
1088         TextureProgramBinding::set(program);
1089         texTransformLocation = program->vertexShader().texTransformLocation();
1090     }
1091     int texTransformLocation;
1092 };
1093
1094 void LayerRendererChromium::drawTextureQuad(const CCTextureDrawQuad* quad)
1095 {
1096     ASSERT(CCProxy::isImplThread());
1097
1098     TexTransformTextureProgramBinding binding;
1099     if (quad->flipped())
1100         binding.set(textureProgramFlip());
1101     else
1102         binding.set(textureProgram());
1103     GLC(context(), context()->useProgram(binding.programId));
1104     GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
1105     const FloatRect& uvRect = quad->uvRect();
1106     GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));
1107
1108     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1109     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
1110
1111     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
1112     // where it will only happen once per texture.
1113     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1114     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1115     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1116     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1117
1118     if (!quad->premultipliedAlpha())
1119         GLC(context(), context()->blendFunc(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1120
1121     WebTransformationMatrix quadTransform = quad->quadTransform();
1122     IntRect quadRect = quad->quadRect();
1123     quadTransform.translate(quadRect.x() + quadRect.width() / 2.0, quadRect.y() + quadRect.height() / 2.0);
1124
1125     drawTexturedQuad(quadTransform, quadRect.width(), quadRect.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
1126
1127     if (!quad->premultipliedAlpha())
1128         GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1129 }
1130
1131 void LayerRendererChromium::drawIOSurfaceQuad(const CCIOSurfaceDrawQuad* quad)
1132 {
1133     ASSERT(CCProxy::isImplThread());
1134     TexTransformTextureProgramBinding binding;
1135     binding.set(textureIOSurfaceProgram());
1136
1137     GLC(context(), context()->useProgram(binding.programId));
1138     GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
1139     GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));
1140
1141     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1142     GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
1143
1144     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
1145     // where it will only happen once per texture.
1146     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1147     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1148     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1149     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1150
1151     const IntSize& bounds = quad->quadRect().size();
1152
1153     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
1154
1155     GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
1156 }
1157
1158 void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const IntSize& hudSize)
1159 {
1160     GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
1161     GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1162     GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1163     useRenderPass(m_defaultRenderPass);
1164
1165     const HeadsUpDisplayProgram* program = headsUpDisplayProgram();
1166     ASSERT(program && program->initialized());
1167     GLC(m_context, m_context->activeTexture(GraphicsContext3D::TEXTURE0));
1168     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(m_context);
1169     hudTexture->bindTexture(ccContext.get(), m_implTextureAllocator.get());
1170     GLC(m_context, m_context->useProgram(program->program()));
1171     GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocation(), 0));
1172
1173     WebTransformationMatrix matrix;
1174     matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
1175     drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
1176                      1, sharedGeometryQuad(), program->vertexShader().matrixLocation(),
1177                      program->fragmentShader().alphaLocation(),
1178                      -1);
1179 }
1180
1181 void LayerRendererChromium::finishDrawingFrame()
1182 {
1183     GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1184     GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
1185
1186     m_implTextureManager->unprotectAllTextures();
1187
1188     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
1189     size_t reclaimLimit = TextureManager::reclaimLimitBytes(viewportSize());
1190     size_t preferredLimit = reclaimLimit > contentsMemoryUseBytes ? reclaimLimit - contentsMemoryUseBytes : 0;
1191     m_implTextureManager->setPreferredMemoryLimitBytes(preferredLimit);
1192     m_implTextureManager->reduceMemoryToLimit(preferredLimit);
1193     m_implTextureManager->deleteEvictedTextures(m_implTextureAllocator.get());
1194 }
1195
1196 void LayerRendererChromium::toGLMatrix(float* flattened, const WebTransformationMatrix& m)
1197 {
1198     flattened[0] = m.m11();
1199     flattened[1] = m.m12();
1200     flattened[2] = m.m13();
1201     flattened[3] = m.m14();
1202     flattened[4] = m.m21();
1203     flattened[5] = m.m22();
1204     flattened[6] = m.m23();
1205     flattened[7] = m.m24();
1206     flattened[8] = m.m31();
1207     flattened[9] = m.m32();
1208     flattened[10] = m.m33();
1209     flattened[11] = m.m34();
1210     flattened[12] = m.m41();
1211     flattened[13] = m.m42();
1212     flattened[14] = m.m43();
1213     flattened[15] = m.m44();
1214 }
1215
1216 void LayerRendererChromium::drawTexturedQuad(const WebTransformationMatrix& drawMatrix,
1217                                              float width, float height, float opacity, const FloatQuad& quad,
1218                                              int matrixLocation, int alphaLocation, int quadLocation)
1219 {
1220     static float glMatrix[16];
1221
1222     WebTransformationMatrix renderMatrix = drawMatrix;
1223
1224     // Apply a scaling factor to size the quad from 1x1 to its intended size.
1225     renderMatrix.scale3d(width, height, 1);
1226
1227     // Apply the projection matrix before sending the transform over to the shader.
1228     toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix);
1229
1230     GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));
1231
1232     if (quadLocation != -1) {
1233         float point[8];
1234         point[0] = quad.p1().x();
1235         point[1] = quad.p1().y();
1236         point[2] = quad.p2().x();
1237         point[3] = quad.p2().y();
1238         point[4] = quad.p3().x();
1239         point[5] = quad.p3().y();
1240         point[6] = quad.p4().x();
1241         point[7] = quad.p4().y();
1242         GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
1243     }
1244
1245     if (alphaLocation != -1)
1246         GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
1247
1248     GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
1249 }
1250
1251 void LayerRendererChromium::copyTextureToFramebuffer(int textureId, const IntSize& bounds, const WebTransformationMatrix& drawMatrix)
1252 {
1253     const RenderPassProgram* program = renderPassProgram();
1254
1255     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1256     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
1257     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1258     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1259     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1260     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1261
1262     GLC(context(), context()->useProgram(program->program()));
1263     GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
1264     drawTexturedQuad(drawMatrix, bounds.width(), bounds.height(), 1, sharedGeometryQuad(),
1265                                     program->vertexShader().matrixLocation(),
1266                                     program->fragmentShader().alphaLocation(),
1267                                     -1);
1268 }
1269
1270 void LayerRendererChromium::setGpuMemoryAllocation(Extensions3DChromium::GpuMemoryAllocationCHROMIUM allocation)
1271 {
1272     if (m_visible && !allocation.gpuResourceSizeInBytes)
1273         return;
1274
1275     if (!allocation.suggestHaveBackbuffer && !m_visible)
1276         discardFramebuffer();
1277
1278     if (!allocation.gpuResourceSizeInBytes) {
1279         releaseRenderPassTextures();
1280         m_client->releaseContentsTextures();
1281         GLC(m_context, m_context->flush());
1282     } else
1283         m_client->setMemoryAllocationLimitBytes(allocation.gpuResourceSizeInBytes);
1284 }
1285
1286 void LayerRendererChromium::finish()
1287 {
1288     TRACE_EVENT("LayerRendererChromium::finish", this, 0);
1289     m_context->finish();
1290 }
1291
1292 bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
1293 {
1294     ASSERT(m_visible);
1295     ASSERT(!m_isFramebufferDiscarded);
1296
1297     TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
1298     // We're done! Time to swapbuffers!
1299
1300     if (m_capabilities.usingPartialSwap) {
1301         // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
1302         IntRect clippedSubBuffer = subBuffer;
1303         clippedSubBuffer.intersect(IntRect(IntPoint::zero(), viewportSize()));
1304         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
1305         int flippedYPosOfRectBottom = viewportHeight() - clippedSubBuffer.y() - clippedSubBuffer.height();
1306         extensions3DChromium->postSubBufferCHROMIUM(clippedSubBuffer.x(), flippedYPosOfRectBottom, clippedSubBuffer.width(), clippedSubBuffer.height());
1307     } else
1308         // Note that currently this has the same effect as swapBuffers; we should
1309         // consider exposing a different entry point on GraphicsContext3D.
1310         m_context->prepareTexture();
1311
1312     return true;
1313 }
1314
1315 void LayerRendererChromium::onSwapBuffersComplete()
1316 {
1317     m_client->onSwapBuffersComplete();
1318 }
1319
1320 void LayerRendererChromium::discardFramebuffer()
1321 {
1322     if (m_isFramebufferDiscarded)
1323         return;
1324
1325     if (!m_capabilities.usingDiscardFramebuffer)
1326         return;
1327
1328     Extensions3D* extensions = m_context->getExtensions();
1329     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1330     // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
1331     extensions3DChromium->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
1332     m_isFramebufferDiscarded = true;
1333
1334     // Damage tracker needs a full reset every time framebuffer is discarded.
1335     m_client->setFullRootLayerDamage();
1336 }
1337
1338 void LayerRendererChromium::ensureFramebuffer()
1339 {
1340     if (!m_isFramebufferDiscarded)
1341         return;
1342
1343     if (!m_capabilities.usingDiscardFramebuffer)
1344         return;
1345
1346     Extensions3D* extensions = m_context->getExtensions();
1347     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1348     extensions3DChromium->ensureFramebufferCHROMIUM();
1349     m_isFramebufferDiscarded = false;
1350 }
1351
1352 void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
1353 {
1354     ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
1355
1356     if (!pixels)
1357         return;
1358
1359     makeContextCurrent();
1360
1361     bool doWorkaround = needsLionIOSurfaceReadbackWorkaround();
1362
1363     Platform3DObject temporaryTexture = NullPlatform3DObject;
1364     Platform3DObject temporaryFBO = NullPlatform3DObject;
1365     GraphicsContext3D* context = m_context.get();
1366
1367     if (doWorkaround) {
1368         // On Mac OS X 10.7, calling glReadPixels against an FBO whose color attachment is an
1369         // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on
1370         // different OpenGL contexts. It is believed that this is the root cause of top crasher
1371         // http://crbug.com/99393. <rdar://problem/10949687>
1372
1373         temporaryTexture = context->createTexture();
1374         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture));
1375         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1376         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1377         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1378         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1379         // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture.
1380         GLC(context, context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, rect.maxX(), rect.maxY(), 0));
1381         temporaryFBO = context->createFramebuffer();
1382         // Attach this texture to an FBO, and perform the readback from that FBO.
1383         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO));
1384         GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0));
1385
1386         ASSERT(context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);
1387     }
1388
1389     GLC(context, context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
1390                                      GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
1391
1392     if (doWorkaround) {
1393         // Clean up.
1394         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1395         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0));
1396         GLC(context, context->deleteFramebuffer(temporaryFBO));
1397         GLC(context, context->deleteTexture(temporaryTexture));
1398     }
1399
1400     if (!m_visible) {
1401         TRACE_EVENT0("cc", "LayerRendererChromium::getFramebufferPixels dropping resources after readback");
1402         discardFramebuffer();
1403         releaseRenderPassTextures();
1404         m_client->releaseContentsTextures();
1405         GLC(m_context, m_context->flush());
1406     }
1407 }
1408
1409 bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const IntRect& deviceRect)
1410 {
1411     if (!texture->reserve(deviceRect.size(), GraphicsContext3D::RGB))
1412         return false;
1413
1414     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(m_context);
1415     texture->bindTexture(ccContext.get(), m_implTextureAllocator.get());
1416     GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(),
1417                                              deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
1418     return true;
1419 }
1420
1421 bool LayerRendererChromium::isCurrentRenderPass(const CCRenderPass* renderPass)
1422 {
1423     return m_currentRenderPass == renderPass && !m_currentManagedTexture;
1424 }
1425
1426 bool LayerRendererChromium::useRenderPass(const CCRenderPass* renderPass)
1427 {
1428     m_currentRenderPass = renderPass;
1429     m_currentManagedTexture = 0;
1430
1431     if (renderPass == m_defaultRenderPass) {
1432         GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1433         setDrawFramebufferRect(renderPass->framebufferOutputRect(), true);
1434         return true;
1435     }
1436
1437     if (!renderPass->targetSurface()->prepareContentsTexture(this))
1438         return false;
1439
1440     return bindFramebufferToTexture(renderPass->targetSurface()->contentsTexture(), renderPass->framebufferOutputRect());
1441 }
1442
1443 bool LayerRendererChromium::useManagedTexture(ManagedTexture* texture, const IntRect& viewportRect)
1444 {
1445     m_currentRenderPass = 0;
1446     m_currentManagedTexture = texture;
1447
1448     return bindFramebufferToTexture(texture, viewportRect);
1449 }
1450
1451 bool LayerRendererChromium::bindFramebufferToTexture(ManagedTexture* texture, const IntRect& framebufferRect)
1452 {
1453     GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
1454
1455     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(m_context);
1456     texture->framebufferTexture2D(ccContext.get(), m_implTextureAllocator.get());
1457
1458 #if !defined ( NDEBUG )
1459     if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1460         ASSERT_NOT_REACHED();
1461         return false;
1462     }
1463 #endif
1464
1465     setDrawFramebufferRect(framebufferRect, false);
1466
1467     return true;
1468 }
1469
1470 // Sets the scissor region to the given rectangle. The coordinate system for the
1471 // scissorRect has its origin at the top left corner of the current visible rect.
1472 void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
1473 {
1474     IntRect framebufferOutputRect = (m_currentRenderPass ? m_currentRenderPass->framebufferOutputRect() : m_defaultRenderPass->framebufferOutputRect());
1475
1476     GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
1477
1478     // The scissor coordinates must be supplied in viewport space so we need to offset
1479     // by the relative position of the top left corner of the current render pass.
1480     int scissorX = scissorRect.x() - framebufferOutputRect.x();
1481     // When rendering to the default render surface we're rendering upside down so the top
1482     // of the GL scissor is the bottom of our layer.
1483     // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
1484     int scissorY;
1485     if (isCurrentRenderPass(m_defaultRenderPass))
1486         scissorY = framebufferOutputRect.height() - (scissorRect.maxY() - framebufferOutputRect.y());
1487     else
1488         scissorY = scissorRect.y() - framebufferOutputRect.y();
1489     GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
1490 }
1491
1492 bool LayerRendererChromium::makeContextCurrent()
1493 {
1494     return m_context->makeContextCurrent();
1495 }
1496
1497 // Sets the coordinate range of content that ends being drawn onto the target render surface.
1498 // The target render surface is assumed to have an origin at 0, 0 and the width and height of
1499 // of the drawRect.
1500 void LayerRendererChromium::setDrawFramebufferRect(const IntRect& drawRect, bool flipY)
1501 {
1502     if (flipY)
1503         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
1504     else
1505         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
1506     GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
1507     m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height());
1508 }
1509
1510
1511 bool LayerRendererChromium::initializeSharedObjects()
1512 {
1513     TRACE_EVENT("LayerRendererChromium::initializeSharedObjects", this, 0);
1514     makeContextCurrent();
1515
1516     // Create an FBO for doing offscreen rendering.
1517     GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
1518
1519     // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
1520     // start while we do other work. Other programs are created lazily on first access.
1521     m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
1522     m_renderPassProgram = adoptPtr(new RenderPassProgram(m_context.get()));
1523     m_tileProgram = adoptPtr(new TileProgram(m_context.get()));
1524     m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context.get()));
1525
1526     GLC(m_context, m_context->flush());
1527
1528     m_implTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
1529                                                   TextureManager::reclaimLimitBytes(viewportSize()),
1530                                                   m_capabilities.maxTextureSize);
1531     m_textureCopier = AcceleratedTextureCopier::create(m_context.get());
1532     if (m_textureUploaderSetting == ThrottledUploader)
1533         m_textureUploader = ThrottledTextureUploader::create(m_context.get());
1534     else
1535         m_textureUploader = UnthrottledTextureUploader::create();
1536     m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1537     m_implTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1538     if (m_capabilities.usingTextureUsageHint)
1539         m_implTextureAllocator->setTextureUsageHint(TrackingTextureAllocator::FramebufferAttachment);
1540     if (m_capabilities.usingTextureStorageExtension) {
1541         m_contentsTextureAllocator->setUseTextureStorageExt(true);
1542         m_implTextureAllocator->setUseTextureStorageExt(true);
1543     }
1544
1545     return true;
1546 }
1547
1548 const LayerRendererChromium::TileCheckerboardProgram* LayerRendererChromium::tileCheckerboardProgram()
1549 {
1550     if (!m_tileCheckerboardProgram)
1551         m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context.get()));
1552     if (!m_tileCheckerboardProgram->initialized()) {
1553         TRACE_EVENT("LayerRendererChromium::checkerboardProgram::initalize", this, 0);
1554         m_tileCheckerboardProgram->initialize(m_context.get());
1555     }
1556     return m_tileCheckerboardProgram.get();
1557 }
1558
1559 const LayerRendererChromium::SolidColorProgram* LayerRendererChromium::solidColorProgram()
1560 {
1561     if (!m_solidColorProgram)
1562         m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context.get()));
1563     if (!m_solidColorProgram->initialized()) {
1564         TRACE_EVENT("LayerRendererChromium::solidColorProgram::initialize", this, 0);
1565         m_solidColorProgram->initialize(m_context.get());
1566     }
1567     return m_solidColorProgram.get();
1568 }
1569
1570 const LayerRendererChromium::HeadsUpDisplayProgram* LayerRendererChromium::headsUpDisplayProgram()
1571 {
1572     if (!m_headsUpDisplayProgram)
1573         m_headsUpDisplayProgram = adoptPtr(new HeadsUpDisplayProgram(m_context.get()));
1574     if (!m_headsUpDisplayProgram->initialized()) {
1575         TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0);
1576         m_headsUpDisplayProgram->initialize(m_context.get());
1577     }
1578     return m_headsUpDisplayProgram.get();
1579 }
1580
1581 const LayerRendererChromium::RenderPassProgram* LayerRendererChromium::renderPassProgram()
1582 {
1583     ASSERT(m_renderPassProgram);
1584     if (!m_renderPassProgram->initialized()) {
1585         TRACE_EVENT("LayerRendererChromium::renderPassProgram::initialize", this, 0);
1586         m_renderPassProgram->initialize(m_context.get());
1587     }
1588     return m_renderPassProgram.get();
1589 }
1590
1591 const LayerRendererChromium::RenderPassProgramAA* LayerRendererChromium::renderPassProgramAA()
1592 {
1593     if (!m_renderPassProgramAA)
1594         m_renderPassProgramAA = adoptPtr(new RenderPassProgramAA(m_context.get()));
1595     if (!m_renderPassProgramAA->initialized()) {
1596         TRACE_EVENT("LayerRendererChromium::renderPassProgramAA::initialize", this, 0);
1597         m_renderPassProgramAA->initialize(m_context.get());
1598     }
1599     return m_renderPassProgramAA.get();
1600 }
1601
1602 const LayerRendererChromium::RenderPassMaskProgram* LayerRendererChromium::renderPassMaskProgram()
1603 {
1604     if (!m_renderPassMaskProgram)
1605         m_renderPassMaskProgram = adoptPtr(new RenderPassMaskProgram(m_context.get()));
1606     if (!m_renderPassMaskProgram->initialized()) {
1607         TRACE_EVENT("LayerRendererChromium::renderPassMaskProgram::initialize", this, 0);
1608         m_renderPassMaskProgram->initialize(m_context.get());
1609     }
1610     return m_renderPassMaskProgram.get();
1611 }
1612
1613 const LayerRendererChromium::RenderPassMaskProgramAA* LayerRendererChromium::renderPassMaskProgramAA()
1614 {
1615     if (!m_renderPassMaskProgramAA)
1616         m_renderPassMaskProgramAA = adoptPtr(new RenderPassMaskProgramAA(m_context.get()));
1617     if (!m_renderPassMaskProgramAA->initialized()) {
1618         TRACE_EVENT("LayerRendererChromium::renderPassMaskProgramAA::initialize", this, 0);
1619         m_renderPassMaskProgramAA->initialize(m_context.get());
1620     }
1621     return m_renderPassMaskProgramAA.get();
1622 }
1623
1624 const LayerRendererChromium::TileProgram* LayerRendererChromium::tileProgram()
1625 {
1626     ASSERT(m_tileProgram);
1627     if (!m_tileProgram->initialized()) {
1628         TRACE_EVENT("LayerRendererChromium::tileProgram::initialize", this, 0);
1629         m_tileProgram->initialize(m_context.get());
1630     }
1631     return m_tileProgram.get();
1632 }
1633
1634 const LayerRendererChromium::TileProgramOpaque* LayerRendererChromium::tileProgramOpaque()
1635 {
1636     ASSERT(m_tileProgramOpaque);
1637     if (!m_tileProgramOpaque->initialized()) {
1638         TRACE_EVENT("LayerRendererChromium::tileProgramOpaque::initialize", this, 0);
1639         m_tileProgramOpaque->initialize(m_context.get());
1640     }
1641     return m_tileProgramOpaque.get();
1642 }
1643
1644 const LayerRendererChromium::TileProgramAA* LayerRendererChromium::tileProgramAA()
1645 {
1646     if (!m_tileProgramAA)
1647         m_tileProgramAA = adoptPtr(new TileProgramAA(m_context.get()));
1648     if (!m_tileProgramAA->initialized()) {
1649         TRACE_EVENT("LayerRendererChromium::tileProgramAA::initialize", this, 0);
1650         m_tileProgramAA->initialize(m_context.get());
1651     }
1652     return m_tileProgramAA.get();
1653 }
1654
1655 const LayerRendererChromium::TileProgramSwizzle* LayerRendererChromium::tileProgramSwizzle()
1656 {
1657     if (!m_tileProgramSwizzle)
1658         m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context.get()));
1659     if (!m_tileProgramSwizzle->initialized()) {
1660         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzle::initialize", this, 0);
1661         m_tileProgramSwizzle->initialize(m_context.get());
1662     }
1663     return m_tileProgramSwizzle.get();
1664 }
1665
1666 const LayerRendererChromium::TileProgramSwizzleOpaque* LayerRendererChromium::tileProgramSwizzleOpaque()
1667 {
1668     if (!m_tileProgramSwizzleOpaque)
1669         m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context.get()));
1670     if (!m_tileProgramSwizzleOpaque->initialized()) {
1671         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleOpaque::initialize", this, 0);
1672         m_tileProgramSwizzleOpaque->initialize(m_context.get());
1673     }
1674     return m_tileProgramSwizzleOpaque.get();
1675 }
1676
1677 const LayerRendererChromium::TileProgramSwizzleAA* LayerRendererChromium::tileProgramSwizzleAA()
1678 {
1679     if (!m_tileProgramSwizzleAA)
1680         m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context.get()));
1681     if (!m_tileProgramSwizzleAA->initialized()) {
1682         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleAA::initialize", this, 0);
1683         m_tileProgramSwizzleAA->initialize(m_context.get());
1684     }
1685     return m_tileProgramSwizzleAA.get();
1686 }
1687
1688 const LayerRendererChromium::TextureProgram* LayerRendererChromium::textureProgram()
1689 {
1690     if (!m_textureProgram)
1691         m_textureProgram = adoptPtr(new TextureProgram(m_context.get()));
1692     if (!m_textureProgram->initialized()) {
1693         TRACE_EVENT("LayerRendererChromium::textureProgram::initialize", this, 0);
1694         m_textureProgram->initialize(m_context.get());
1695     }
1696     return m_textureProgram.get();
1697 }
1698
1699 const LayerRendererChromium::TextureProgramFlip* LayerRendererChromium::textureProgramFlip()
1700 {
1701     if (!m_textureProgramFlip)
1702         m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context.get()));
1703     if (!m_textureProgramFlip->initialized()) {
1704         TRACE_EVENT("LayerRendererChromium::textureProgramFlip::initialize", this, 0);
1705         m_textureProgramFlip->initialize(m_context.get());
1706     }
1707     return m_textureProgramFlip.get();
1708 }
1709
1710 const LayerRendererChromium::TextureIOSurfaceProgram* LayerRendererChromium::textureIOSurfaceProgram()
1711 {
1712     if (!m_textureIOSurfaceProgram)
1713         m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context.get()));
1714     if (!m_textureIOSurfaceProgram->initialized()) {
1715         TRACE_EVENT("LayerRendererChromium::textureIOSurfaceProgram::initialize", this, 0);
1716         m_textureIOSurfaceProgram->initialize(m_context.get());
1717     }
1718     return m_textureIOSurfaceProgram.get();
1719 }
1720
1721 const LayerRendererChromium::VideoYUVProgram* LayerRendererChromium::videoYUVProgram()
1722 {
1723     if (!m_videoYUVProgram)
1724         m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context.get()));
1725     if (!m_videoYUVProgram->initialized()) {
1726         TRACE_EVENT("LayerRendererChromium::videoYUVProgram::initialize", this, 0);
1727         m_videoYUVProgram->initialize(m_context.get());
1728     }
1729     return m_videoYUVProgram.get();
1730 }
1731
1732 const LayerRendererChromium::VideoStreamTextureProgram* LayerRendererChromium::videoStreamTextureProgram()
1733 {
1734     if (!m_videoStreamTextureProgram)
1735         m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context.get()));
1736     if (!m_videoStreamTextureProgram->initialized()) {
1737         TRACE_EVENT("LayerRendererChromium::streamTextureProgram::initialize", this, 0);
1738         m_videoStreamTextureProgram->initialize(m_context.get());
1739     }
1740     return m_videoStreamTextureProgram.get();
1741 }
1742
1743 void LayerRendererChromium::cleanupSharedObjects()
1744 {
1745     makeContextCurrent();
1746
1747     m_sharedGeometry.clear();
1748
1749     if (m_tileProgram)
1750         m_tileProgram->cleanup(m_context.get());
1751     if (m_tileProgramOpaque)
1752         m_tileProgramOpaque->cleanup(m_context.get());
1753     if (m_tileProgramSwizzle)
1754         m_tileProgramSwizzle->cleanup(m_context.get());
1755     if (m_tileProgramSwizzleOpaque)
1756         m_tileProgramSwizzleOpaque->cleanup(m_context.get());
1757     if (m_tileProgramAA)
1758         m_tileProgramAA->cleanup(m_context.get());
1759     if (m_tileProgramSwizzleAA)
1760         m_tileProgramSwizzleAA->cleanup(m_context.get());
1761     if (m_tileCheckerboardProgram)
1762         m_tileCheckerboardProgram->cleanup(m_context.get());
1763
1764     if (m_renderPassMaskProgram)
1765         m_renderPassMaskProgram->cleanup(m_context.get());
1766     if (m_renderPassProgram)
1767         m_renderPassProgram->cleanup(m_context.get());
1768     if (m_renderPassMaskProgramAA)
1769         m_renderPassMaskProgramAA->cleanup(m_context.get());
1770     if (m_renderPassProgramAA)
1771         m_renderPassProgramAA->cleanup(m_context.get());
1772
1773     if (m_textureProgram)
1774         m_textureProgram->cleanup(m_context.get());
1775     if (m_textureProgramFlip)
1776         m_textureProgramFlip->cleanup(m_context.get());
1777     if (m_textureIOSurfaceProgram)
1778         m_textureIOSurfaceProgram->cleanup(m_context.get());
1779
1780     if (m_videoYUVProgram)
1781         m_videoYUVProgram->cleanup(m_context.get());
1782     if (m_videoStreamTextureProgram)
1783         m_videoStreamTextureProgram->cleanup(m_context.get());
1784
1785     if (m_solidColorProgram)
1786         m_solidColorProgram->cleanup(m_context.get());
1787
1788     if (m_headsUpDisplayProgram)
1789         m_headsUpDisplayProgram->cleanup(m_context.get());
1790
1791     if (m_offscreenFramebufferId)
1792         GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
1793
1794     m_textureCopier.clear();
1795     m_textureUploader.clear();
1796
1797     releaseRenderPassTextures();
1798 }
1799
1800 bool LayerRendererChromium::isContextLost()
1801 {
1802     return (m_context.get()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR);
1803 }
1804
1805 } // namespace WebCore
1806
1807 #endif // USE(ACCELERATED_COMPOSITING)