[TextureMapper] Tiles are not created for large textures
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapperGL.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Library General Public License for more details.
13
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB.  If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "TextureMapperGL.h"
22
23 #include "GraphicsContext.h"
24 #include "Image.h"
25 #include "TextureMapperShaderManager.h"
26 #include "Timer.h"
27 #include <wtf/HashMap.h>
28 #include <wtf/OwnArrayPtr.h>
29 #include <wtf/PassOwnArrayPtr.h>
30 #include <wtf/PassRefPtr.h>
31 #include <wtf/RefCounted.h>
32
33 #if PLATFORM(QT)
34 #if QT_VERSION >= 0x050000
35 #include <QOpenGLContext>
36 #include <QPlatformPixmap>
37 #else
38 #include <QGLContext>
39 #endif // QT_VERSION
40 #elif OS(WINDOWS)
41 #include <windows.h>
42 #elif OS(MAC_OS_X)
43 #include <AGL/agl.h>
44 #elif defined(XP_UNIX)
45 #include <GL/glx.h>
46 #endif
47
48 #if USE(CAIRO)
49 #include "CairoUtilities.h"
50 #include "RefPtrCairo.h"
51 #include <cairo.h>
52 #endif
53
54 #define GL_CMD(...) do { __VA_ARGS__; ASSERT_ARG(__VA_ARGS__, !glGetError()); } while (0)
55 namespace WebCore {
56 struct TextureMapperGLData {
57     struct SharedGLData : public RefCounted<SharedGLData> {
58 #if PLATFORM(QT)
59 #if QT_VERSION >= 0x050000
60         typedef QOpenGLContext* GLContext;
61         static GLContext getCurrentGLContext()
62         {
63             return QOpenGLContext::currentContext();
64         }
65 #else
66         typedef const QGLContext* GLContext;
67         static GLContext getCurrentGLContext()
68         {
69             return QGLContext::currentContext();
70         }
71 #endif
72 #elif OS(WINDOWS)
73         typedef HGLRC GLContext;
74         static GLContext getCurrentGLContext()
75         {
76             return wglGetCurrentContext();
77         }
78 #elif OS(MAC_OS_X)
79         typedef AGLContext GLContext;
80         static GLContext getCurrentGLContext()
81         {
82             return aglGetCurrentContext();
83         }
84 #elif defined(XP_UNIX)
85         typedef GLXContext GLContext;
86         static GLContext getCurrentGLContext()
87         {
88             return glXGetCurrentContext();
89         }
90 #else
91         // Default implementation for unknown opengl.
92         // Returns always increasing number and disables GL context data sharing.
93         typedef unsigned int GLContext;
94         static GLContext getCurrentGLContext()
95         {
96             static GLContext dummyContextCounter = 0;
97             return ++dummyContextCounter;
98         }
99
100 #endif
101
102         typedef HashMap<GLContext, SharedGLData*> GLContextDataMap;
103         static GLContextDataMap& glContextDataMap()
104         {
105             static GLContextDataMap map;
106             return map;
107         }
108
109         static PassRefPtr<SharedGLData> currentSharedGLData()
110         {
111             GLContext currentGLConext = getCurrentGLContext();
112             GLContextDataMap::iterator it = glContextDataMap().find(currentGLConext);
113             if (it != glContextDataMap().end())
114                 return it->second;
115
116             return adoptRef(new SharedGLData(getCurrentGLContext()));
117         }
118
119
120
121         TextureMapperShaderManager textureMapperShaderManager;
122
123         SharedGLData(GLContext glContext)
124         {
125             glContextDataMap().add(glContext, this);
126         }
127
128         ~SharedGLData()
129         {
130             GLContextDataMap::const_iterator end = glContextDataMap().end();
131             GLContextDataMap::iterator it;
132             for (it = glContextDataMap().begin(); it != end; ++it) {
133                 if (it->second == this)
134                     break;
135             }
136
137             ASSERT(it != end);
138             glContextDataMap().remove(it);
139         }
140     };
141
142     SharedGLData& sharedGLData() const
143     {
144         return *(m_sharedGLData.get());
145     }
146
147     void initializeStencil();
148
149     TextureMapperGLData()
150         : PaintFlags(0)
151         , previousProgram(0)
152         , targetFrameBuffer(0)
153         , didModifyStencil(false)
154         , previousScissorState(0)
155         , previousDepthState(0)
156         , m_sharedGLData(TextureMapperGLData::SharedGLData::currentSharedGLData())
157     { }
158
159     TransformationMatrix projectionMatrix;
160     TextureMapper::PaintFlags PaintFlags;
161     GLint previousProgram;
162     GLint targetFrameBuffer;
163     bool didModifyStencil;
164     GLint previousScissorState;
165     GLint previousDepthState;
166     GLint viewport[4];
167     GLint previousScissor[4];
168     RefPtr<SharedGLData> m_sharedGLData;
169     RefPtr<BitmapTexture> currentSurface;
170 };
171
172 void TextureMapperGL::ClipStack::init(const IntRect& rect)
173 {
174     clipStack.clear();
175     clipState = TextureMapperGL::ClipState(rect);
176 }
177
178 void TextureMapperGL::ClipStack::push()
179 {
180     clipStack.append(clipState);
181 }
182
183 void TextureMapperGL::ClipStack::pop()
184 {
185     if (clipStack.isEmpty())
186         return;
187     clipState = clipStack.last();
188     clipStack.removeLast();
189 }
190
191 static void scissorClip(const IntRect& rect)
192 {
193     if (rect.isEmpty())
194         return;
195
196     GLint viewport[4];
197     GL_CMD(glGetIntegerv(GL_VIEWPORT, viewport));
198     GL_CMD(glScissor(rect.x(), viewport[3] - rect.maxY(), rect.width(), rect.height()));
199 }
200
201 void TextureMapperGL::ClipStack::apply()
202 {
203     scissorClip(clipState.scissorBox);
204     GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
205     GL_CMD(glStencilFunc(GL_EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1));
206     if (clipState.stencilIndex == 1)
207         GL_CMD(glDisable(GL_STENCIL_TEST));
208     else
209         GL_CMD(glEnable(GL_STENCIL_TEST));
210 }
211
212
213 void TextureMapperGLData::initializeStencil()
214 {
215     if (currentSurface) {
216         static_cast<BitmapTextureGL*>(currentSurface.get())->initializeStencil();
217         return;
218     }
219
220     if (didModifyStencil)
221         return;
222
223     GL_CMD(glClearStencil(0));
224     GL_CMD(glClear(GL_STENCIL_BUFFER_BIT));
225     didModifyStencil = true;
226 }
227
228 BitmapTextureGL* toBitmapTextureGL(BitmapTexture* texture)
229 {
230     if (!texture || !texture->isBackedByOpenGL())
231         return 0;
232
233     return static_cast<BitmapTextureGL*>(texture);
234 }
235
236 TextureMapperGL::TextureMapperGL()
237     : m_data(new TextureMapperGLData)
238     , m_context(0)
239 {
240 }
241
242 TextureMapperGL::ClipStack& TextureMapperGL::clipStack()
243 {
244     return data().currentSurface ? toBitmapTextureGL(data().currentSurface.get())->m_clipStack : m_clipStack;
245 }
246
247 void TextureMapperGL::beginPainting(PaintFlags flags)
248 {
249     // Make sure that no GL error code stays from previous operations.
250     glGetError();
251
252     if (!initializeOpenGLShims())
253         return;
254
255     GL_CMD(glGetIntegerv(GL_CURRENT_PROGRAM, &data().previousProgram));
256     data().previousScissorState = glIsEnabled(GL_SCISSOR_TEST);
257     data().previousDepthState = glIsEnabled(GL_DEPTH_TEST);
258     glDisable(GL_DEPTH_TEST);
259     glEnable(GL_SCISSOR_TEST);
260 #if PLATFORM(QT)
261     if (m_context) {
262         QPainter* painter = m_context->platformContext();
263         painter->save();
264         painter->beginNativePainting();
265     }
266 #endif
267     data().didModifyStencil = false;
268     GL_CMD(glDepthMask(0));
269     GL_CMD(glGetIntegerv(GL_VIEWPORT, data().viewport));
270     GL_CMD(glGetIntegerv(GL_SCISSOR_BOX, data().previousScissor));
271     glGetIntegerv(GL_FRAMEBUFFER_BINDING, &data().targetFrameBuffer);
272     m_clipStack.init(IntRect(0, 0, data().viewport[2], data().viewport[3]));
273     GL_CMD(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &data().targetFrameBuffer));
274     data().PaintFlags = flags;
275     bindSurface(0);
276 }
277
278 void TextureMapperGL::endPainting()
279 {
280     if (data().didModifyStencil) {
281         glClearStencil(1);
282         glClear(GL_STENCIL_BUFFER_BIT);
283     }
284
285     glUseProgram(data().previousProgram);
286
287     glScissor(data().previousScissor[0], data().previousScissor[1], data().previousScissor[2], data().previousScissor[3]);
288     if (data().previousScissorState)
289         glEnable(GL_SCISSOR_TEST);
290     else
291         glDisable(GL_SCISSOR_TEST);
292
293     if (data().previousDepthState)
294         glEnable(GL_DEPTH_TEST);
295     else
296         glDisable(GL_DEPTH_TEST);
297
298 #if PLATFORM(QT)
299     if (!m_context)
300         return;
301     QPainter* painter = m_context->platformContext();
302     painter->endNativePainting();
303     painter->restore();
304 #endif
305 }
306
307 void TextureMapperGL::drawRect(const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GLenum drawingMode, bool needsBlending)
308 {
309     GL_CMD(glEnableVertexAttribArray(shaderProgram->vertexAttrib()));
310     GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0));
311     const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
312     GL_CMD(glVertexAttribPointer(shaderProgram->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect));
313
314     TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
315             targetRect.width(), 0, 0, 0,
316             0, targetRect.height(), 0, 0,
317             0, 0, 1, 0,
318             targetRect.x(), targetRect.y(), 0, 1));
319
320     const GLfloat m4[] = {
321         matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
322         matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
323         matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
324         matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
325     };
326     GL_CMD(glUniformMatrix4fv(shaderProgram->matrixVariable(), 1, GL_FALSE, m4));
327
328     if (needsBlending) {
329         GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
330         GL_CMD(glEnable(GL_BLEND));
331     } else
332         GL_CMD(glDisable(GL_BLEND));
333
334     GL_CMD(glDrawArrays(drawingMode, 0, 4));
335     GL_CMD(glDisableVertexAttribArray(shaderProgram->vertexAttrib()));
336 }
337
338 void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix)
339 {
340     if (clipStack().current().scissorBox.isEmpty())
341         return;
342
343     RefPtr<TextureMapperShaderProgramSolidColor> shaderInfo = data().sharedGLData().textureMapperShaderManager.solidColorProgram();
344     GL_CMD(glUseProgram(shaderInfo->id()));
345
346     float alpha = color.alpha() / 255.0;
347     GL_CMD(glUniform4f(shaderInfo->colorVariable(),
348                        (color.red() / 255.0) * alpha,
349                        (color.green() / 255.0) * alpha,
350                        (color.blue() / 255.0) * alpha,
351                        alpha));
352     GL_CMD(glLineWidth(width));
353
354     drawRect(targetRect, modelViewMatrix, shaderInfo.get(), GL_LINE_LOOP, color.hasAlpha());
355 }
356
357 void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* mask)
358 {
359     if (!texture.isValid())
360         return;
361
362     if (clipStack().current().scissorBox.isEmpty())
363         return;
364
365     const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
366     drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : SupportsBlending, textureGL.size(), targetRect, matrix, opacity, mask);
367 }
368
369 void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture)
370 {
371     RefPtr<TextureMapperShaderProgram> shaderInfo;
372     if (maskTexture)
373         shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::OpacityAndMask);
374     else
375         shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple);
376     GL_CMD(glUseProgram(shaderInfo->id()));
377
378     GL_CMD(glEnableVertexAttribArray(shaderInfo->vertexAttrib()));
379     GL_CMD(glActiveTexture(GL_TEXTURE0));
380     GL_CMD(glBindTexture(GL_TEXTURE_2D, texture));
381     GL_CMD(glUniform1i(shaderInfo->sourceTextureVariable(), 0));
382
383     const GLfloat m4src[] = {
384         1, 0, 0, 0,
385         0, (flags & ShouldFlipTexture) ? -1 : 1, 0, 0,
386         0, 0, 1, 0,
387         0, (flags & ShouldFlipTexture) ? 1 : 0, 0, 1};
388     GL_CMD(glUniformMatrix4fv(shaderInfo->sourceMatrixVariable(), 1, GL_FALSE, m4src));
389
390     shaderInfo->prepare(opacity, maskTexture);
391
392     bool needsBlending = (flags & SupportsBlending) || opacity < 0.99 || maskTexture;
393     drawRect(targetRect, modelViewMatrix, shaderInfo.get(), GL_TRIANGLE_FAN, needsBlending);
394 }
395
396 bool BitmapTextureGL::canReuseWith(const IntSize& contentsSize, Flags)
397 {
398     return contentsSize == m_textureSize;
399 }
400
401 #if OS(DARWIN)
402 #define DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
403 #else
404 #define DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE GL_UNSIGNED_BYTE
405 #endif
406
407 static void swizzleBGRAToRGBA(uint32_t* data, const IntRect& rect, int stride = 0)
408 {
409     stride = stride ? stride : rect.width();
410     for (int y = rect.y(); y < rect.maxY(); ++y) {
411         uint32_t* p = data + y * stride;
412         for (int x = rect.x(); x < rect.maxX(); ++x)
413             p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
414     }
415 }
416
417 static bool driverSupportsBGRASwizzling()
418 {
419 #if defined(TEXMAP_OPENGL_ES_2)
420     // FIXME: Implement reliable detection. See also https://bugs.webkit.org/show_bug.cgi?id=81103.
421     return false;
422 #else
423     return true;
424 #endif
425 }
426
427 static bool driverSupportsSubImage()
428 {
429 #if defined(TEXMAP_OPENGL_ES_2)
430     // FIXME: Implement reliable detection.
431     return false;
432 #else
433     return true;
434 #endif
435 }
436
437 void BitmapTextureGL::didReset()
438 {
439     if (!m_id)
440         GL_CMD(glGenTextures(1, &m_id));
441
442     m_shouldClear = true;
443     if (m_textureSize == contentSize())
444         return;
445
446     GLuint format = driverSupportsBGRASwizzling() ? GL_BGRA : GL_RGBA;
447
448     m_textureSize = contentSize();
449     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id));
450     GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
451     GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
452     GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
453     GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
454     GL_CMD(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0));
455 }
456
457
458 void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine)
459 {
460     GLuint glFormat = GL_RGBA;
461     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id));
462
463     if (driverSupportsBGRASwizzling())
464         glFormat = GL_BGRA;
465     else
466         swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(const_cast<void*>(data)), IntRect(sourceOffset, targetRect.size()), bytesPerLine / 4);
467
468     if (bytesPerLine == targetRect.width() / 4 && sourceOffset == IntPoint::zero()) {
469         GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data));
470         return;
471     }
472
473     // For ES drivers that don't support sub-images, transfer the pixels row-by-row.
474     if (!driverSupportsSubImage()) {
475         const char* bits = static_cast<const char*>(data);
476         for (int y = 0; y < targetRect.height(); ++y) {
477             const char *row = bits + ((sourceOffset.y() + y) * bytesPerLine + sourceOffset.x() * 4);
478             GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y() + y, targetRect.width(), 1, glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, row));
479         }
480         return;
481     }
482
483 #if !defined(TEXMAP_OPENGL_ES_2)
484     // Use the OpenGL sub-image extension, now that we know it's available.
485     GL_CMD(glPixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / 4));
486     GL_CMD(glPixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()));
487     GL_CMD(glPixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()));
488     GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data));
489     GL_CMD(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
490     GL_CMD(glPixelStorei(GL_UNPACK_SKIP_ROWS, 0));
491     GL_CMD(glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0));
492 #endif
493 }
494
495 void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset)
496 {
497     if (!image)
498         return;
499     NativeImagePtr frameImage = image->nativeImageForCurrentFrame();
500     if (!frameImage)
501         return;
502
503     int bytesPerLine;
504     const char* imageData;
505
506 #if PLATFORM(QT)
507     QImage qtImage;
508 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
509     // With QPA, we can avoid a deep copy.
510     qtImage = *frameImage->handle()->buffer();
511 #else
512     // This might be a deep copy, depending on other references to the pixmap.
513     qtImage = frameImage->toImage();
514 #endif
515     imageData = reinterpret_cast<const char*>(qtImage.constBits());
516     bytesPerLine = qtImage.bytesPerLine();
517 #elif USE(CAIRO)
518     cairo_surface_t* surface = frameImage->surface();
519     imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface));
520     bytesPerLine = cairo_image_surface_get_stride(surface);
521 #endif
522
523     updateContents(imageData, targetRect, offset, bytesPerLine);
524 }
525
526 #if ENABLE(CSS_FILTERS)
527 void TextureMapperGL::drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation& filter)
528 {
529     // For standard filters, we always draw the whole texture without transformations.
530     RefPtr<StandardFilterProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderForFilter(filter);
531     if (!program) {
532         drawTexture(sourceTexture, FloatRect(FloatPoint::zero(), sourceTexture.size()), TransformationMatrix(), 1, 0);
533         return;
534     }
535     GL_CMD(glEnableVertexAttribArray(program->vertexAttrib()));
536     GL_CMD(glEnableVertexAttribArray(program->texCoordAttrib()));
537     GL_CMD(glActiveTexture(GL_TEXTURE0));
538     GL_CMD(glBindTexture(GL_TEXTURE_2D, static_cast<const BitmapTextureGL&>(sourceTexture).id()));
539     glUniform1i(program->textureUniform(), 0);
540     const GLfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1};
541     const GLfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1};
542     GL_CMD(glVertexAttribPointer(program->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, targetVertices));
543     GL_CMD(glVertexAttribPointer(program->texCoordAttrib(), 2, GL_FLOAT, GL_FALSE, 0, sourceVertices));
544     GL_CMD(glDisable(GL_BLEND));
545     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
546     GL_CMD(glDisableVertexAttribArray(program->vertexAttrib()));
547     GL_CMD(glDisableVertexAttribArray(program->texCoordAttrib()));
548 }
549
550 PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
551 {
552     RefPtr<BitmapTexture> previousSurface = m_textureMapper->data().currentSurface;
553
554     RefPtr<BitmapTexture> source = this;
555     RefPtr<BitmapTexture> target = m_textureMapper->acquireTextureFromPool(m_textureSize);
556     for (int i = 0; i < filters.size(); ++i) {
557         const FilterOperation* filter = filters.at(i);
558         ASSERT(filter);
559
560         m_textureMapper->bindSurface(target.get());
561         m_textureMapper->drawFiltered(i ? *source.get() : contentTexture, contentTexture, *filter);
562         std::swap(source, target);
563     }
564
565     m_textureMapper->bindSurface(previousSurface.get());
566     return source;
567 }
568 #endif
569
570 static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool mirrored)
571 {
572     const float near = 9999999;
573     const float far = -99999;
574
575     return TransformationMatrix(2.0 / float(size.width()), 0, 0, 0,
576                                 0, (mirrored ? 2.0 : -2.0) / float(size.height()), 0, 0,
577                                 0, 0, -2.f / (far - near), 0,
578                                 -1, mirrored ? -1 : 1, -(far + near) / (far - near), 1);
579 }
580
581 void BitmapTextureGL::initializeStencil()
582 {
583     if (m_rbo)
584         return;
585     GL_CMD(glGenRenderbuffers(1, &m_rbo));
586     GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo));
587 #ifdef TEXMAP_OPENGL_ES_2
588     GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()));
589 #else
590     GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()));
591 #endif
592     GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, 0));
593     GL_CMD(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo));
594     GL_CMD(glClearStencil(0));
595     GL_CMD(glClear(GL_STENCIL_BUFFER_BIT));
596 }
597
598 void BitmapTextureGL::clearIfNeeded()
599 {
600     if (!m_shouldClear)
601         return;
602
603     m_clipStack.init(IntRect(IntPoint::zero(), m_textureSize));
604     m_clipStack.apply();
605     GL_CMD(glClearColor(0, 0, 0, 0));
606     GL_CMD(glClear(GL_COLOR_BUFFER_BIT));
607     m_shouldClear = false;
608 }
609
610 void BitmapTextureGL::createFboIfNeeded()
611 {
612     if (m_fbo)
613         return;
614
615     GL_CMD(glGenFramebuffers(1, &m_fbo));
616     GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo));
617     GL_CMD(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id(), 0));
618     m_shouldClear = true;
619 }
620
621 void BitmapTextureGL::bind()
622 {
623     GL_CMD(glBindTexture(GL_TEXTURE_2D, 0));
624     createFboIfNeeded();
625     GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo));
626     GL_CMD(glViewport(0, 0, m_textureSize.width(), m_textureSize.height()));
627     clearIfNeeded();
628     m_textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */);
629     m_clipStack.apply();
630 }
631
632 BitmapTextureGL::~BitmapTextureGL()
633 {
634     if (m_id)
635         GL_CMD(glDeleteTextures(1, &m_id));
636
637     if (m_fbo)
638         GL_CMD(glDeleteFramebuffers(1, &m_fbo));
639
640     if (m_rbo)
641         GL_CMD(glDeleteRenderbuffers(1, &m_rbo));
642 }
643
644 bool BitmapTextureGL::isValid() const
645 {
646     return m_id;
647 }
648
649 IntSize BitmapTextureGL::size() const
650 {
651     return m_textureSize;
652 }
653
654 TextureMapperGL::~TextureMapperGL()
655 {
656     delete m_data;
657 }
658
659 void TextureMapperGL::bindDefaultSurface()
660 {
661     GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, data().targetFrameBuffer));
662     IntSize viewportSize(data().viewport[2], data().viewport[3]);
663     data().projectionMatrix = createProjectionMatrix(viewportSize, data().PaintFlags & PaintingMirrored);
664     GL_CMD(glViewport(data().viewport[0], data().viewport[1], viewportSize.width(), viewportSize.height()));
665     m_clipStack.apply();
666     data().currentSurface.clear();
667 }
668
669 void TextureMapperGL::bindSurface(BitmapTexture *surface)
670 {
671     if (!surface) {
672         bindDefaultSurface();
673         return;
674     }
675
676     static_cast<BitmapTextureGL*>(surface)->bind();
677     data().currentSurface = surface;
678 }
679
680 bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
681 {
682     // 3D transforms are currently not supported in scissor clipping
683     // resulting in cropped surfaces when z>0.
684     if (!modelViewMatrix.isAffine())
685         return false;
686
687     FloatQuad quad = modelViewMatrix.projectQuad(targetRect);
688     IntRect rect = quad.enclosingBoundingBox();
689
690     // Only use scissors on rectilinear clips.
691     if (!quad.isRectilinear() || rect.isEmpty())
692         return false;
693
694     clipStack().current().scissorBox.intersect(rect);
695     clipStack().apply();
696     return true;
697 }
698
699 void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
700 {
701     clipStack().push();
702     if (beginScissorClip(modelViewMatrix, targetRect))
703         return;
704
705     data().initializeStencil();
706
707     RefPtr<TextureMapperShaderProgram> shaderInfo = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple);
708
709     GL_CMD(glUseProgram(shaderInfo->id()));
710     GL_CMD(glEnableVertexAttribArray(shaderInfo->vertexAttrib()));
711     const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
712     GL_CMD(glVertexAttribPointer(shaderInfo->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, unitRect));
713
714     TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix)
715             .multiply(modelViewMatrix)
716             .multiply(TransformationMatrix(targetRect.width(), 0, 0, 0,
717                 0, targetRect.height(), 0, 0,
718                 0, 0, 1, 0,
719                 targetRect.x(), targetRect.y(), 0, 1));
720
721     const GLfloat m4[] = {
722         matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
723         matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
724         matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
725         matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
726     };
727
728     const GLfloat m4all[] = {
729         2, 0, 0, 0,
730         0, 2, 0, 0,
731         0, 0, 1, 0,
732         -1, -1, 0, 1
733     };
734
735     int& stencilIndex = clipStack().current().stencilIndex;
736
737     GL_CMD(glEnable(GL_STENCIL_TEST));
738
739     // Make sure we don't do any actual drawing.
740     GL_CMD(glStencilFunc(GL_NEVER, stencilIndex, stencilIndex));
741
742     // Operate only on the stencilIndex and above.
743     GL_CMD(glStencilMask(0xff & ~(stencilIndex - 1)));
744
745     // First clear the entire buffer at the current index.
746     GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4all));
747     GL_CMD(glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
748     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
749
750     // Now apply the current index to the new quad.
751     GL_CMD(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
752     GL_CMD(glUniformMatrix4fv(shaderInfo->matrixVariable(), 1, GL_FALSE, m4));
753     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
754
755     // Clear the state.
756     GL_CMD(glDisableVertexAttribArray(shaderInfo->vertexAttrib()));
757     GL_CMD(glStencilMask(0));
758
759     // Increase stencilIndex and apply stencil testing.
760     stencilIndex *= 2;
761     clipStack().apply();
762 }
763
764 void TextureMapperGL::endClip()
765 {
766     clipStack().pop();
767     clipStack().apply();
768 }
769
770 PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
771 {
772     BitmapTextureGL* texture = new BitmapTextureGL();
773     texture->setTextureMapper(this);
774     return adoptRef(texture);
775 }
776
777 PassOwnPtr<TextureMapper> TextureMapper::platformCreateAccelerated()
778 {
779     return TextureMapperGL::create();
780 }
781
782 };