4dae6135790aae7eedb3806e2ff4a31f09059c27
[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 "Canvas2DLayerChromium.h"
38 #include "Extensions3DChromium.h"
39 #include "FloatQuad.h"
40 #include "GeometryBinding.h"
41 #include "GraphicsContext3D.h"
42 #include "LayerChromium.h"
43 #include "LayerPainterChromium.h"
44 #include "ManagedTexture.h"
45 #include "LayerTextureUpdaterCanvas.h"
46 #include "NonCompositedContentHost.h"
47 #include "NotImplemented.h"
48 #include "PlatformColor.h"
49 #include "RenderSurfaceChromium.h"
50 #include "TextStream.h"
51 #include "TextureManager.h"
52 #include "TreeSynchronizer.h"
53 #include "TraceEvent.h"
54 #include "WebGLLayerChromium.h"
55 #include "cc/CCLayerImpl.h"
56 #include "cc/CCLayerTreeHostCommon.h"
57 #include "cc/CCMainThreadTask.h"
58 #if USE(SKIA)
59 #include "Extensions3D.h"
60 #include "GrContext.h"
61 #include "NativeImageSkia.h"
62 #include "PlatformContextSkia.h"
63 #elif USE(CG)
64 #include <CoreGraphics/CGBitmapContext.h>
65 #endif
66 #include <wtf/CurrentTime.h>
67 #include <wtf/MainThread.h>
68
69 using namespace std;
70
71 namespace WebCore {
72
73 namespace {
74
75 static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
76 {
77     float deltaX = right - left;
78     float deltaY = top - bottom;
79     TransformationMatrix ortho;
80     if (!deltaX || !deltaY)
81         return ortho;
82     ortho.setM11(2.0f / deltaX);
83     ortho.setM41(-(right + left) / deltaX);
84     ortho.setM22(2.0f / deltaY);
85     ortho.setM42(-(top + bottom) / deltaY);
86
87     // Z component of vertices is always set to zero as we don't use the depth buffer
88     // while drawing.
89     ortho.setM33(0);
90
91     return ortho;
92 }
93
94 static TransformationMatrix screenMatrix(int x, int y, int width, int height)
95 {
96     TransformationMatrix screen;
97
98     // Map to viewport.
99     screen.translate3d(x, y, 0);
100     screen.scale3d(width, height, 0);
101
102     // Map x, y and z to unit square.
103     screen.translate3d(0.5, 0.5, 0.5);
104     screen.scale3d(0.5, 0.5, 0.5);
105
106     return screen;
107 }
108
109 #if USE(SKIA)
110 bool contextSupportsAcceleratedPainting(GraphicsContext3D* context)
111 {
112     WebCore::Extensions3D* extensions = context->getExtensions();
113     if (extensions->supports("GL_EXT_texture_format_BGRA8888"))
114         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
115     else
116         return false;
117
118     if (extensions->supports("GL_EXT_read_format_bgra"))
119         extensions->ensureEnabled("GL_EXT_read_format_bgra");
120     else
121         return false;
122
123     if (!context->grContext())
124         return false;
125
126     return true;
127 }
128 #endif
129
130 } // anonymous namespace
131
132 PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(CCLayerTreeHostImpl* owner, PassRefPtr<GraphicsContext3D> context)
133 {
134 #if USE(SKIA)
135     if (owner->settings().acceleratePainting && !contextSupportsAcceleratedPainting(context.get()))
136         return nullptr;
137 #endif
138     OwnPtr<LayerRendererChromium> layerRenderer(adoptPtr(new LayerRendererChromium(owner, context)));
139     if (!layerRenderer->initialize())
140         return nullptr;
141
142     return layerRenderer.release();
143 }
144
145 LayerRendererChromium::LayerRendererChromium(CCLayerTreeHostImpl* owner,
146                                              PassRefPtr<GraphicsContext3D> context)
147     : m_owner(owner)
148     , m_currentRenderSurface(0)
149     , m_offscreenFramebufferId(0)
150     , m_zoomAnimatorScale(1)
151     , m_contentsTextureMemoryUseBytes(0)
152     , m_context(context)
153     , m_defaultRenderSurface(0)
154     , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
155 {
156 }
157
158 bool LayerRendererChromium::initialize()
159 {
160     m_context->makeContextCurrent();
161     if (settings().acceleratePainting) {
162         m_capabilities.usingAcceleratedPainting = true;
163     }
164
165     WebCore::Extensions3D* extensions = m_context->getExtensions();
166     m_capabilities.usingMapSub = extensions->supports("GL_CHROMIUM_map_sub");
167     if (m_capabilities.usingMapSub)
168         extensions->ensureEnabled("GL_CHROMIUM_map_sub");
169
170     GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
171     m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get());
172
173     if (!initializeSharedObjects())
174         return false;
175
176     m_headsUpDisplay = CCHeadsUpDisplay::create(this);
177
178     // Make sure the viewport and context gets initialized, even if it is to zero.
179     viewportChanged();
180     return true;
181 }
182
183 LayerRendererChromium::~LayerRendererChromium()
184 {
185     m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies.
186     cleanupSharedObjects();
187 }
188
189 void LayerRendererChromium::clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* layer)
190 {
191     for (size_t i = 0; i < layer->children().size(); ++i)
192         clearRenderSurfacesOnCCLayerImplRecursive(layer->children()[i].get());
193     layer->clearRenderSurface();
194 }
195
196 void LayerRendererChromium::close()
197 {
198     if (rootLayer())
199         clearRenderSurfacesOnCCLayerImplRecursive(rootLayer());
200 }
201
202 GraphicsContext3D* LayerRendererChromium::context()
203 {
204     return m_context.get();
205 }
206
207 void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line)
208 {
209     unsigned long error = context->getError();
210     if (error != GraphicsContext3D::NO_ERROR)
211         LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
212 }
213
214 void LayerRendererChromium::releaseRenderSurfaceTextures()
215 {
216     m_renderSurfaceTextureManager->evictAndDeleteAllTextures(m_context.get());
217 }
218
219 void LayerRendererChromium::viewportChanged()
220 {
221     if (m_context)
222         m_context->reshape(std::max(1, viewportWidth()), std::max(1, viewportHeight()));
223
224     // Reset the current render surface to force an update of the viewport and
225     // projection matrix next time useRenderSurface is called.
226     m_currentRenderSurface = 0;
227 }
228
229 void LayerRendererChromium::drawLayers()
230 {
231     // FIXME: use the frame begin time from the overall compositor scheduler.
232     // This value is currently inaccessible because it is up in Chromium's
233     // RenderWidget.
234     m_headsUpDisplay->onFrameBegin(currentTime());
235
236     if (!rootLayer())
237         return;
238
239     m_renderSurfaceTextureManager->setMemoryLimitBytes(TextureManager::highLimitBytes() - m_contentsTextureMemoryUseBytes);
240     drawLayersInternal();
241
242     if (TextureManager::reclaimLimitBytes() > m_contentsTextureMemoryUseBytes)
243         m_renderSurfaceTextureManager->reduceMemoryToLimit(TextureManager::reclaimLimitBytes() - m_contentsTextureMemoryUseBytes);
244     else
245         m_renderSurfaceTextureManager->reduceMemoryToLimit(0);
246     m_renderSurfaceTextureManager->deleteEvictedTextures(m_context.get());
247
248     if (settings().compositeOffscreen)
249         copyOffscreenTextureToDisplay();
250 }
251
252 void LayerRendererChromium::drawLayersInternal()
253 {
254     if (viewportSize().isEmpty() || !rootLayer())
255         return;
256
257     TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
258     CCLayerImpl* rootDrawLayer = rootLayer();
259     makeContextCurrent();
260
261     if (!rootDrawLayer->renderSurface())
262         rootDrawLayer->createRenderSurface();
263     rootDrawLayer->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize()));
264
265     rootDrawLayer->setScissorRect(IntRect(IntPoint(), viewportSize()));
266
267     CCLayerList renderSurfaceLayerList;
268     renderSurfaceLayerList.append(rootDrawLayer);
269
270     TransformationMatrix zoomMatrix;
271     zoomMatrix.scale3d(m_zoomAnimatorScale, m_zoomAnimatorScale, 1);
272     m_defaultRenderSurface = rootDrawLayer->renderSurface();
273     m_defaultRenderSurface->clearLayerList();
274
275     {
276         TRACE_EVENT("LayerRendererChromium::drawLayersInternal::calcDrawEtc", this, 0);
277         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootDrawLayer, rootDrawLayer, zoomMatrix, zoomMatrix, renderSurfaceLayerList, m_defaultRenderSurface->layerList(), &m_layerSorter, m_capabilities.maxTextureSize);
278     }
279
280     // The GL viewport covers the entire visible area, including the scrollbars.
281     GLC(m_context.get(), m_context->viewport(0, 0, viewportWidth(), viewportHeight()));
282     m_windowMatrix = screenMatrix(0, 0, viewportWidth(), viewportHeight());
283
284     // Bind the common vertex attributes used for drawing all the layers.
285     m_sharedGeometry->prepareForDraw();
286
287     GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
288     GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
289     GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
290
291     useRenderSurface(m_defaultRenderSurface);
292
293     // Clear to blue to make it easier to spot unrendered regions.
294     m_context->clearColor(0, 0, 1, 1);
295     m_context->colorMask(true, true, true, true);
296     m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
297
298     GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
299     GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
300     GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
301
302     // Update the contents of the render surfaces. We traverse the array from
303     // back to front to guarantee that nested render surfaces get rendered in the
304     // correct order.
305     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
306         CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
307         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
308         ASSERT(renderSurface);
309
310         renderSurface->setSkipsDraw(true);
311
312         // Render surfaces whose drawable area has zero width or height
313         // will have no layers associated with them and should be skipped.
314         if (!renderSurface->layerList().size())
315             continue;
316
317         // Skip completely transparent render surfaces.
318         if (!renderSurface->drawOpacity())
319             continue;
320
321         if (useRenderSurface(renderSurface)) {
322             renderSurface->setSkipsDraw(false);
323
324             if (renderSurfaceLayer != rootDrawLayer) {
325                 GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
326                 GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
327                 GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
328                 GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
329             }
330
331             const CCLayerList& layerList = renderSurface->layerList();
332             for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
333                 drawLayer(layerList[layerIndex].get(), renderSurface);
334         }
335     }
336
337     if (m_headsUpDisplay->enabled()) {
338         GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
339         GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
340         GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
341         useRenderSurface(m_defaultRenderSurface);
342         m_headsUpDisplay->draw();
343     }
344
345     GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
346     GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
347 }
348
349 void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
350 {
351     flattened[0] = m.m11();
352     flattened[1] = m.m12();
353     flattened[2] = m.m13();
354     flattened[3] = m.m14();
355     flattened[4] = m.m21();
356     flattened[5] = m.m22();
357     flattened[6] = m.m23();
358     flattened[7] = m.m24();
359     flattened[8] = m.m31();
360     flattened[9] = m.m32();
361     flattened[10] = m.m33();
362     flattened[11] = m.m34();
363     flattened[12] = m.m41();
364     flattened[13] = m.m42();
365     flattened[14] = m.m43();
366     flattened[15] = m.m44();
367 }
368
369 void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMatrix,
370                                              float width, float height, float opacity, const FloatQuad& quad,
371                                              int matrixLocation, int alphaLocation, int quadLocation)
372 {
373     static float glMatrix[16];
374
375     TransformationMatrix renderMatrix = drawMatrix;
376
377     // Apply a scaling factor to size the quad from 1x1 to its intended size.
378     renderMatrix.scale3d(width, height, 1);
379
380     // Apply the projection matrix before sending the transform over to the shader.
381     toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix);
382
383     GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1));
384
385     if (quadLocation != -1) {
386         float point[8];
387         point[0] = quad.p1().x();
388         point[1] = quad.p1().y();
389         point[2] = quad.p2().x();
390         point[3] = quad.p2().y();
391         point[4] = quad.p3().x();
392         point[5] = quad.p3().y();
393         point[6] = quad.p4().x();
394         point[7] = quad.p4().y();
395         GLC(m_context, m_context->uniform2fv(quadLocation, point, 4));
396     }
397
398     if (alphaLocation != -1)
399         GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
400
401     GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
402 }
403
404 void LayerRendererChromium::finish()
405 {
406     TRACE_EVENT("LayerRendererChromium::finish", this, 0);
407     m_context->finish();
408 }
409
410 void LayerRendererChromium::present()
411 {
412     TRACE_EVENT("LayerRendererChromium::present", this, 0);
413     // We're done! Time to swapbuffers!
414
415     // Note that currently this has the same effect as swapBuffers; we should
416     // consider exposing a different entry point on GraphicsContext3D.
417     m_context->prepareTexture();
418
419     m_headsUpDisplay->onPresent();
420 }
421
422 void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
423 {
424     ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
425
426     if (!pixels)
427         return;
428
429     makeContextCurrent();
430
431     GLC(m_context.get(), m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
432                                          GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
433 }
434
435 // FIXME: This method should eventually be replaced by a proper texture manager.
436 unsigned LayerRendererChromium::createLayerTexture()
437 {
438     unsigned textureId = 0;
439     GLC(m_context.get(), textureId = m_context->createTexture());
440     GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
441     // Do basic linear filtering on resize.
442     GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
443     GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
444     // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
445     GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
446     GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
447     return textureId;
448 }
449
450 void LayerRendererChromium::deleteLayerTexture(unsigned textureId)
451 {
452     if (!textureId)
453         return;
454
455     GLC(m_context.get(), m_context->deleteTexture(textureId));
456 }
457
458 // Returns true if any part of the layer falls within the visibleRect
459 bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const TransformationMatrix& matrix, const IntRect& visibleRect)
460 {
461     // Form the matrix used by the shader to map the corners of the layer's
462     // bounds into clip space.
463     TransformationMatrix renderMatrix = matrix;
464     renderMatrix.scale3d(layer->bounds().width(), layer->bounds().height(), 1);
465     renderMatrix = m_projectionMatrix * renderMatrix;
466
467     FloatRect layerRect(-0.5, -0.5, 1, 1);
468     FloatRect mappedRect = renderMatrix.mapRect(layerRect);
469
470     // The layer is visible if it intersects any part of a rectangle whose origin
471     // is at (-1, -1) and size is 2x2.
472     return mappedRect.intersects(FloatRect(-1, -1, 2, 2));
473 }
474
475 ManagedTexture* LayerRendererChromium::getOffscreenLayerTexture()
476 {
477     return settings().compositeOffscreen && rootLayer() ? rootLayer()->renderSurface()->contentsTexture() : 0;
478 }
479
480 void LayerRendererChromium::copyOffscreenTextureToDisplay()
481 {
482     if (settings().compositeOffscreen) {
483         makeContextCurrent();
484
485         useRenderSurface(0);
486         TransformationMatrix drawTransform;
487         drawTransform.translate3d(0.5 * m_defaultRenderSurface->contentRect().width(), 0.5 * m_defaultRenderSurface->contentRect().height(), 0);
488         m_defaultRenderSurface->setDrawTransform(drawTransform);
489         m_defaultRenderSurface->setDrawOpacity(1);
490         m_defaultRenderSurface->draw(this, m_defaultRenderSurface->contentRect());
491     }
492 }
493
494 bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface)
495 {
496     if (m_currentRenderSurface == renderSurface)
497         return true;
498
499     m_currentRenderSurface = renderSurface;
500
501     if ((renderSurface == m_defaultRenderSurface && !settings().compositeOffscreen) || (!renderSurface && settings().compositeOffscreen)) {
502         GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
503         if (renderSurface)
504             setDrawViewportRect(renderSurface->contentRect(), true);
505         else
506             setDrawViewportRect(m_defaultRenderSurface->contentRect(), true);
507         return true;
508     }
509
510     GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
511
512     if (!renderSurface->prepareContentsTexture(this))
513         return false;
514
515     renderSurface->contentsTexture()->framebufferTexture2D(m_context.get());
516
517 #if !defined ( NDEBUG )
518     if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
519         ASSERT_NOT_REACHED();
520         return false;
521     }
522 #endif
523
524     setDrawViewportRect(renderSurface->contentRect(), false);
525     return true;
526 }
527
528 void LayerRendererChromium::drawLayer(CCLayerImpl* layer, CCRenderSurface* targetSurface)
529 {
530     if (layer->renderSurface() && layer->renderSurface() != targetSurface) {
531         layer->renderSurface()->draw(this, layer->getDrawRect());
532         layer->renderSurface()->releaseContentsTexture();
533         return;
534     }
535
536     if (!layer->drawsContent())
537         return;
538
539     if (!layer->opacity())
540         return;
541
542     if (layer->bounds().isEmpty())
543         return;
544
545     IntRect targetSurfaceRect = layer->targetRenderSurface() ? layer->targetRenderSurface()->contentRect() : m_defaultRenderSurface->contentRect();
546     if (layer->usesLayerScissor()) {
547         IntRect scissorRect = layer->scissorRect();
548         targetSurfaceRect.intersect(scissorRect);
549         if (targetSurfaceRect.isEmpty())
550             return;
551         setScissorToRect(scissorRect);
552     } else
553         GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
554
555     // The layer should not be drawn if (1) it is not double-sided and (2) the back of the layer is facing the screen.
556     // This second condition is checked by computing the transformed normal of the layer.
557     if (!layer->doubleSided()) {
558         FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds()));
559         FloatQuad mappedLayer = layer->screenSpaceTransform().mapQuad(FloatQuad(layerRect));
560         FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1();
561         FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1();
562         FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0);
563         FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0);
564         FloatPoint3D zAxis = xAxis.cross(yAxis);
565         if (zAxis.z() < 0)
566             return;
567     }
568
569     layer->draw(this);
570
571     // Draw the debug border if there is one.
572     layer->drawDebugBorder(this);
573 }
574
575 // Sets the scissor region to the given rectangle. The coordinate system for the
576 // scissorRect has its origin at the top left corner of the current visible rect.
577 void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
578 {
579     IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->contentRect() : m_defaultRenderSurface->contentRect());
580
581     GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
582
583     // The scissor coordinates must be supplied in viewport space so we need to offset
584     // by the relative position of the top left corner of the current render surface.
585     int scissorX = scissorRect.x() - contentRect.x();
586     // When rendering to the default render surface we're rendering upside down so the top
587     // of the GL scissor is the bottom of our layer.
588     // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
589     int scissorY;
590     if (m_currentRenderSurface == m_defaultRenderSurface && !settings().compositeOffscreen)
591         scissorY = m_currentRenderSurface->contentRect().height() - (scissorRect.maxY() - m_currentRenderSurface->contentRect().y());
592     else
593         scissorY = scissorRect.y() - contentRect.y();
594     GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
595 }
596
597 bool LayerRendererChromium::makeContextCurrent()
598 {
599     m_context->makeContextCurrent();
600     return true;
601 }
602
603 // Sets the coordinate range of content that ends being drawn onto the target render surface.
604 // The target render surface is assumed to have an origin at 0, 0 and the width and height of
605 // of the drawRect.
606 void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
607 {
608     if (flipY)
609         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
610     else
611         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
612     GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
613     m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height());
614 }
615
616
617 bool LayerRendererChromium::initializeSharedObjects()
618 {
619     TRACE_EVENT("LayerRendererChromium::initializeSharedObjects", this, 0);
620     makeContextCurrent();
621
622     // Create an FBO for doing offscreen rendering.
623     GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
624
625     // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
626     // start while we do other work. Other programs are created lazily on first access.
627     m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
628     m_renderSurfaceProgram = adoptPtr(new CCRenderSurface::Program(m_context.get()));
629     m_tilerProgram = adoptPtr(new CCTiledLayerImpl::Program(m_context.get()));
630
631     GLC(m_context.get(), m_context->flush());
632
633     m_renderSurfaceTextureManager = TextureManager::create(TextureManager::highLimitBytes(), m_capabilities.maxTextureSize);
634     return true;
635 }
636
637 const LayerChromium::BorderProgram* LayerRendererChromium::borderProgram()
638 {
639     if (!m_borderProgram)
640         m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get()));
641     if (!m_borderProgram->initialized()) {
642         TRACE_EVENT("LayerRendererChromium::borderProgram::initialize", this, 0);
643         m_borderProgram->initialize(m_context.get());
644     }
645     return m_borderProgram.get();
646 }
647
648 const CCHeadsUpDisplay::Program* LayerRendererChromium::headsUpDisplayProgram()
649 {
650     if (!m_headsUpDisplayProgram)
651         m_headsUpDisplayProgram = adoptPtr(new CCHeadsUpDisplay::Program(m_context.get()));
652     if (!m_headsUpDisplayProgram->initialized()) {
653         TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0);
654         m_headsUpDisplayProgram->initialize(m_context.get());
655     }
656     return m_headsUpDisplayProgram.get();
657 }
658
659 const CCRenderSurface::Program* LayerRendererChromium::renderSurfaceProgram()
660 {
661     ASSERT(m_renderSurfaceProgram);
662     if (!m_renderSurfaceProgram->initialized()) {
663         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgram::initialize", this, 0);
664         m_renderSurfaceProgram->initialize(m_context.get());
665     }
666     return m_renderSurfaceProgram.get();
667 }
668
669 const CCRenderSurface::ProgramAA* LayerRendererChromium::renderSurfaceProgramAA()
670 {
671     if (!m_renderSurfaceProgramAA)
672         m_renderSurfaceProgramAA = adoptPtr(new CCRenderSurface::ProgramAA(m_context.get()));
673     if (!m_renderSurfaceProgramAA->initialized()) {
674         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgramAA::initialize", this, 0);
675         m_renderSurfaceProgramAA->initialize(m_context.get());
676     }
677     return m_renderSurfaceProgramAA.get();
678 }
679
680 const CCRenderSurface::MaskProgram* LayerRendererChromium::renderSurfaceMaskProgram()
681 {
682     if (!m_renderSurfaceMaskProgram)
683         m_renderSurfaceMaskProgram = adoptPtr(new CCRenderSurface::MaskProgram(m_context.get()));
684     if (!m_renderSurfaceMaskProgram->initialized()) {
685         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgram::initialize", this, 0);
686         m_renderSurfaceMaskProgram->initialize(m_context.get());
687     }
688     return m_renderSurfaceMaskProgram.get();
689 }
690
691 const CCRenderSurface::MaskProgramAA* LayerRendererChromium::renderSurfaceMaskProgramAA()
692 {
693     if (!m_renderSurfaceMaskProgramAA)
694         m_renderSurfaceMaskProgramAA = adoptPtr(new CCRenderSurface::MaskProgramAA(m_context.get()));
695     if (!m_renderSurfaceMaskProgramAA->initialized()) {
696         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgramAA::initialize", this, 0);
697         m_renderSurfaceMaskProgramAA->initialize(m_context.get());
698     }
699     return m_renderSurfaceMaskProgramAA.get();
700 }
701
702 const CCTiledLayerImpl::Program* LayerRendererChromium::tilerProgram()
703 {
704     ASSERT(m_tilerProgram);
705     if (!m_tilerProgram->initialized()) {
706         TRACE_EVENT("LayerRendererChromium::tilerProgram::initialize", this, 0);
707         m_tilerProgram->initialize(m_context.get());
708     }
709     return m_tilerProgram.get();
710 }
711
712 const CCTiledLayerImpl::ProgramAA* LayerRendererChromium::tilerProgramAA()
713 {
714     if (!m_tilerProgramAA)
715         m_tilerProgramAA = adoptPtr(new CCTiledLayerImpl::ProgramAA(m_context.get()));
716     if (!m_tilerProgramAA->initialized()) {
717         TRACE_EVENT("LayerRendererChromium::tilerProgramAA::initialize", this, 0);
718         m_tilerProgramAA->initialize(m_context.get());
719     }
720     return m_tilerProgramAA.get();
721 }
722
723 const CCTiledLayerImpl::ProgramSwizzle* LayerRendererChromium::tilerProgramSwizzle()
724 {
725     if (!m_tilerProgramSwizzle)
726         m_tilerProgramSwizzle = adoptPtr(new CCTiledLayerImpl::ProgramSwizzle(m_context.get()));
727     if (!m_tilerProgramSwizzle->initialized()) {
728         TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzle::initialize", this, 0);
729         m_tilerProgramSwizzle->initialize(m_context.get());
730     }
731     return m_tilerProgramSwizzle.get();
732 }
733
734 const CCTiledLayerImpl::ProgramSwizzleAA* LayerRendererChromium::tilerProgramSwizzleAA()
735 {
736     if (!m_tilerProgramSwizzleAA)
737         m_tilerProgramSwizzleAA = adoptPtr(new CCTiledLayerImpl::ProgramSwizzleAA(m_context.get()));
738     if (!m_tilerProgramSwizzleAA->initialized()) {
739         TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzleAA::initialize", this, 0);
740         m_tilerProgramSwizzleAA->initialize(m_context.get());
741     }
742     return m_tilerProgramSwizzleAA.get();
743 }
744
745 const CCCanvasLayerImpl::Program* LayerRendererChromium::canvasLayerProgram()
746 {
747     if (!m_canvasLayerProgram)
748         m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get()));
749     if (!m_canvasLayerProgram->initialized()) {
750         TRACE_EVENT("LayerRendererChromium::canvasLayerProgram::initialize", this, 0);
751         m_canvasLayerProgram->initialize(m_context.get());
752     }
753     return m_canvasLayerProgram.get();
754 }
755
756 const CCPluginLayerImpl::Program* LayerRendererChromium::pluginLayerProgram()
757 {
758     if (!m_pluginLayerProgram)
759         m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get()));
760     if (!m_pluginLayerProgram->initialized()) {
761         TRACE_EVENT("LayerRendererChromium::pluginLayerProgram::initialize", this, 0);
762         m_pluginLayerProgram->initialize(m_context.get());
763     }
764     return m_pluginLayerProgram.get();
765 }
766
767 const CCVideoLayerImpl::RGBAProgram* LayerRendererChromium::videoLayerRGBAProgram()
768 {
769     if (!m_videoLayerRGBAProgram)
770         m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get()));
771     if (!m_videoLayerRGBAProgram->initialized()) {
772         TRACE_EVENT("LayerRendererChromium::videoLayerRGBAProgram::initialize", this, 0);
773         m_videoLayerRGBAProgram->initialize(m_context.get());
774     }
775     return m_videoLayerRGBAProgram.get();
776 }
777
778 const CCVideoLayerImpl::YUVProgram* LayerRendererChromium::videoLayerYUVProgram()
779 {
780     if (!m_videoLayerYUVProgram)
781         m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get()));
782     if (!m_videoLayerYUVProgram->initialized()) {
783         TRACE_EVENT("LayerRendererChromium::videoLayerYUVProgram::initialize", this, 0);
784         m_videoLayerYUVProgram->initialize(m_context.get());
785     }
786     return m_videoLayerYUVProgram.get();
787 }
788
789
790 void LayerRendererChromium::cleanupSharedObjects()
791 {
792     makeContextCurrent();
793
794     m_sharedGeometry.clear();
795
796     if (m_borderProgram)
797         m_borderProgram->cleanup(m_context.get());
798     if (m_headsUpDisplayProgram)
799         m_headsUpDisplayProgram->cleanup(m_context.get());
800     if (m_tilerProgram)
801         m_tilerProgram->cleanup(m_context.get());
802     if (m_tilerProgramAA)
803         m_tilerProgramAA->cleanup(m_context.get());
804     if (m_tilerProgramSwizzle)
805         m_tilerProgramSwizzle->cleanup(m_context.get());
806     if (m_tilerProgramSwizzleAA)
807         m_tilerProgramSwizzleAA->cleanup(m_context.get());
808     if (m_canvasLayerProgram)
809         m_canvasLayerProgram->cleanup(m_context.get());
810     if (m_pluginLayerProgram)
811         m_pluginLayerProgram->cleanup(m_context.get());
812     if (m_renderSurfaceMaskProgram)
813         m_renderSurfaceMaskProgram->cleanup(m_context.get());
814     if (m_renderSurfaceMaskProgramAA)
815         m_renderSurfaceMaskProgramAA->cleanup(m_context.get());
816     if (m_renderSurfaceProgram)
817         m_renderSurfaceProgram->cleanup(m_context.get());
818     if (m_renderSurfaceProgramAA)
819         m_renderSurfaceProgramAA->cleanup(m_context.get());
820     if (m_videoLayerRGBAProgram)
821         m_videoLayerRGBAProgram->cleanup(m_context.get());
822     if (m_videoLayerYUVProgram)
823         m_videoLayerYUVProgram->cleanup(m_context.get());
824
825     m_borderProgram.clear();
826     m_headsUpDisplayProgram.clear();
827     m_tilerProgram.clear();
828     m_tilerProgramAA.clear();
829     m_tilerProgramSwizzle.clear();
830     m_tilerProgramSwizzleAA.clear();
831     m_canvasLayerProgram.clear();
832     m_pluginLayerProgram.clear();
833     m_renderSurfaceMaskProgram.clear();
834     m_renderSurfaceMaskProgramAA.clear();
835     m_renderSurfaceProgram.clear();
836     m_renderSurfaceProgramAA.clear();
837     m_videoLayerRGBAProgram.clear();
838     m_videoLayerYUVProgram.clear();
839     if (m_offscreenFramebufferId)
840         GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
841
842     ASSERT(!m_contentsTextureMemoryUseBytes);
843     releaseRenderSurfaceTextures();
844 }
845
846 String LayerRendererChromium::layerTreeAsText() const
847 {
848     TextStream ts;
849     if (rootLayer()) {
850         ts << rootLayer()->layerTreeAsText();
851         ts << "RenderSurfaces:\n";
852         dumpRenderSurfaces(ts, 1, rootLayer());
853     }
854     return ts.release();
855 }
856
857 void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, const CCLayerImpl* layer) const
858 {
859     if (layer->renderSurface())
860         layer->renderSurface()->dumpSurface(ts, indent);
861
862     for (size_t i = 0; i < layer->children().size(); ++i)
863         dumpRenderSurfaces(ts, indent, layer->children()[i].get());
864 }
865
866 bool LayerRendererChromium::isContextLost()
867 {
868     return (m_context.get()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR);
869 }
870
871 } // namespace WebCore
872
873 #endif // USE(ACCELERATED_COMPOSITING)