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