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