[Qt][Texmap] Convert shaders in TextureMapperGL to use a macro
[WebKit-https.git] / Source / WebCore / platform / graphics / opengl / 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
22 #include "TextureMapperGL.h"
23
24 #include "GraphicsContext.h"
25 #include "Image.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 #include <cairo/OpenGLShims.h>
35 #elif defined(TEXMAP_OPENGL_ES_2)
36 #include <GLES2/gl2.h>
37 #include <GLES2/gl2ext.h>
38 #elif OS(MAC_OS_X)
39 #include <gl.h>
40 #else
41 #include <GL/gl.h>
42 #endif
43
44 #if !defined(TEXMAP_OPENGL_ES_2) && !PLATFORM(QT)
45 extern "C" {
46     void glUniform1f(GLint, GLfloat);
47     void glUniform1i(GLint, GLint);
48     void glVertexAttribPointer(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
49     void glUniform4f(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
50     void glShaderSource(GLuint, GLsizei, const char**, const GLint*);
51     GLuint glCreateShader(GLenum);
52     void glShaderSource(GLuint, GLsizei, const char**, const GLint*);
53     void glCompileShader(GLuint);
54     void glDeleteShader(GLuint);
55     void glUniformMatrix4fv(GLint, GLsizei, GLboolean, const GLfloat*);
56     GLuint glCreateProgram();
57     void glAttachShader(GLuint, GLuint);
58     void glLinkProgram(GLuint);
59     void glUseProgram(GLuint);
60     void glDisableVertexAttribArray(GLuint);
61     void glEnableVertexAttribArray(GLuint);
62     void glBindFramebuffer(GLenum target, GLuint framebuffer);
63     void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
64     void glGenFramebuffers(GLsizei n, GLuint* framebuffers);
65     void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
66     void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
67     void glBindBuffer(GLenum, GLuint);
68     void glDeleteBuffers(GLsizei, const GLuint*);
69     void glGenBuffers(GLsizei, GLuint*);
70     void glBufferData(GLenum, GLsizeiptr, const GLvoid*, GLenum);
71     void glBufferSubData(GLenum, GLsizeiptr, GLsizeiptr, const GLvoid*);
72     void glGetProgramInfoLog(GLuint, GLsizei, GLsizei*, GLchar*);
73     void glGetShaderInfoLog(GLuint, GLsizei, GLsizei*, GLchar*);
74     void glGenRenderbuffers(GLsizei n, GLuint* ids);
75     void glDeleteRenderbuffers(GLsizei n, const GLuint* ids);
76     void glBindRenderbuffer(GLenum target, GLuint id);
77     void glRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
78     void glFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbufferId);
79     GLenum glCheckFramebufferStatus(GLenum target);
80     GLint glGetAttribLocation(GLuint program, const GLchar* name);
81 #if !OS(MAC_OS_X)
82     GLint glGetUniformLocation(GLuint, const GLchar*);
83     GLint glBindAttribLocation(GLuint, GLuint, const GLchar*);
84 #endif
85 }
86 #endif
87
88 namespace WebCore {
89
90 inline static void debugGLCommand(const char* command, int line)
91 {
92     const GLenum err = glGetError();
93     if (!err)
94         return;
95     WTFReportError(__FILE__, line, WTF_PRETTY_FUNCTION, "[TextureMapper GL] Command failed: %s (%x)\n", command, err);
96     ASSERT_NOT_REACHED();
97 }
98
99 #ifndef NDEBUG
100 #define GL_CMD(x) {x, debugGLCommand(#x, __LINE__); }
101 #else
102 #define GL_CMD(x) x;
103 #endif
104
105 struct TextureMapperGLData {
106     static struct GlobalGLData {
107         enum ShaderProgramIndex {
108             NoProgram = -1,
109             SimpleProgram,
110             OpacityAndMaskProgram,
111             ClipProgram,
112
113             ProgramCount
114         };
115
116         enum ShaderVariableIndex {
117             InMatrixVariable,
118             InSourceMatrixVariable,
119             InMaskMatrixVariable,
120             OpacityVariable,
121             SourceTextureVariable,
122             MaskTextureVariable,
123
124             VariableCount
125         };
126
127         struct ProgramInfo {
128             GLuint id;
129             GLuint vertexAttrib;
130             GLint vars[VariableCount];
131         };
132
133         GLint getUniformLocation(ShaderProgramIndex prog, ShaderVariableIndex var, const char* name)
134         {
135             return programs[prog].vars[var] = glGetUniformLocation(programs[prog].id, name);
136         }
137
138         void createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource, ShaderProgramIndex index)
139         {
140             GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
141             GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
142             GL_CMD(glShaderSource(vertexShader, 1, &vertexShaderSource, 0))
143             GL_CMD(glShaderSource(fragmentShader, 1, &fragmentShaderSource, 0))
144             GLuint programID = glCreateProgram();
145             GL_CMD(glCompileShader(vertexShader))
146             GL_CMD(glCompileShader(fragmentShader))
147             GL_CMD(glAttachShader(programID, vertexShader))
148             GL_CMD(glAttachShader(programID, fragmentShader))
149             GL_CMD(glLinkProgram(programID))
150             programs[index].vertexAttrib = glGetAttribLocation(programID, "InVertex");
151             programs[index].id = programID;
152         }
153
154         ProgramInfo programs[ProgramCount];
155
156         int stencilIndex;
157
158         GlobalGLData()
159             : stencilIndex(1)
160         { }
161     } globalGLData;
162
163     struct DirectlyCompositedImageRepository {
164         struct Entry {
165             GLuint texture;
166             int refCount;
167         };
168         typedef HashMap<ImageUID, Entry> ImageTextureMap;
169         ImageTextureMap imageToTexture;
170
171         GLuint findOrCreate(ImageUID image, bool& found)
172         {
173             ImageTextureMap::iterator it = imageToTexture.find(image);
174             found = false;
175             if (it != imageToTexture.end()) {
176                 it->second.refCount++;
177                 found = true;
178                 return it->second.texture;
179             }
180             Entry entry;
181             GL_CMD(glGenTextures(1, &entry.texture));
182             entry.refCount = 1;
183             imageToTexture.add(image, entry);
184             return entry.texture;
185         }
186
187         bool deref(ImageUID image)
188         {
189             HashMap<ImageUID, Entry>::iterator it = imageToTexture.find(image);
190             if (it != imageToTexture.end()) {
191                 if (it->second.refCount < 2) {
192                     imageToTexture.remove(it);
193                     return false;
194                 }
195             }
196             return true;
197         }
198
199         DirectlyCompositedImageRepository()
200         {
201         }
202
203         ~DirectlyCompositedImageRepository()
204         {
205             for (ImageTextureMap::iterator it = imageToTexture.begin(); it != imageToTexture.end(); ++it) {
206                 GLuint texture = it->second.texture;
207                 if (texture)
208                     GL_CMD(glDeleteTextures(1, &texture));
209             }
210
211         }
212     } directlyCompositedImages;
213
214     TextureMapperGLData()
215         : currentProgram(TextureMapperGLData::GlobalGLData::NoProgram)
216     { }
217
218     TransformationMatrix projectionMatrix;
219     int currentProgram;
220     int previousProgram;
221 };
222
223 TextureMapperGLData::GlobalGLData TextureMapperGLData::globalGLData;
224
225 class BitmapTextureGL : public BitmapTexture {
226 public:
227     virtual void destroy();
228     virtual IntSize size() const;
229     virtual bool isValid() const;
230     virtual void reset(const IntSize&, bool opaque);
231     void bind();
232     virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect);
233     virtual void endPaint();
234     virtual void setContentsToImage(Image*);
235     ~BitmapTextureGL() { destroy(); }
236     virtual uint32_t id() const { return m_id; }
237     inline bool isOpaque() const { return m_opaque; }
238     inline FloatSize relativeSize() const { return m_relativeSize; }
239     void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; }
240
241     void updateContents(PixelFormat, const IntRect&, void*);
242     void pack()
243     {
244         // This is currently a stub.
245         if (isPacked())
246             return;
247         m_isPacked = true;
248     }
249
250     void unpack()
251     {
252         // This is currently a stub.
253         if (!isPacked())
254             return;
255         m_isPacked = false;
256     }
257
258     bool isPacked() const
259     {
260         return m_isPacked;
261     }
262
263 private:
264     GLuint m_id;
265     ImageUID m_imageUID;
266     FloatSize m_relativeSize;
267     bool m_opaque;
268     IntSize m_textureSize;
269     OwnPtr<BGRA32PremultimpliedBuffer> m_buffer;
270     IntRect m_dirtyRect;
271     GLuint m_fbo;
272     GLuint m_rbo;
273     IntSize m_actualSize;
274     bool m_surfaceNeedsReset;
275     bool m_isPacked;
276     TextureMapperGL* m_textureMapper;
277     BitmapTextureGL()
278         : m_id(0)
279         , m_imageUID(0)
280         , m_opaque(false)
281         , m_fbo(0)
282         , m_rbo(0)
283         , m_surfaceNeedsReset(true)
284         , m_textureMapper(0)
285     {
286     }
287
288     friend class TextureMapperGL;
289 };
290
291 #define TEXMAP_GET_SHADER_VAR_LOCATION(prog, var) \
292     if (TextureMapperGLData::globalGLData.getUniformLocation(TextureMapperGLData::globalGLData.prog##Program, TextureMapperGLData::globalGLData.var##Variable, #var) < 0) \
293             LOG_ERROR("Couldn't find variable "#var" in program "#prog"\n");
294
295 #define TEXMAP_BUILD_SHADER(program) \
296     TextureMapperGLData::globalGLData.createShaderProgram(vertexShaderSource##program, fragmentShaderSource##program, TextureMapperGLData::globalGLData.program##Program);
297
298 TextureMapperGL::TextureMapperGL()
299     : m_data(new TextureMapperGLData)
300     , m_context(0)
301 {
302 }
303
304 void TextureMapperGL::initializeShaders()
305 {
306     static bool shadersCompiled = false;
307     if (shadersCompiled)
308         return;
309     shadersCompiled = true;
310 #ifndef TEXMAP_OPENGL_ES_2
311 #define OES2_PRECISION_DEFINITIONS \
312     "#define lowp\n#define highp\n"
313 #define OES2_FRAGMENT_SHADER_DEFAULT_PRECISION
314 #else
315 #define OES2_PRECISION_DEFINITIONS
316 #define OES2_FRAGMENT_SHADER_DEFAULT_PRECISION \
317     "precision mediump float; \n"
318 #endif
319
320 #define VERTEX_SHADER(src...) OES2_PRECISION_DEFINITIONS#src
321 #define FRAGMENT_SHADER(src...) OES2_PRECISION_DEFINITIONS\
322                                 OES2_FRAGMENT_SHADER_DEFAULT_PRECISION\
323                                 #src
324
325     const char* fragmentShaderSourceOpacityAndMask =
326         FRAGMENT_SHADER(
327             uniform sampler2D SourceTexture, MaskTexture;
328             uniform lowp float Opacity;
329             varying highp vec2 OutTexCoordSource, OutTexCoordMask;
330             void main(void)
331             {
332                 lowp vec4 color = texture2D(SourceTexture, OutTexCoordSource);
333                 lowp vec4 maskColor = texture2D(MaskTexture, OutTexCoordMask);
334                 lowp float fragmentAlpha = Opacity * maskColor.a;
335                 gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
336             }
337         );
338
339     const char* vertexShaderSourceOpacityAndMask =
340         VERTEX_SHADER(
341             uniform mat4 InMatrix, InSourceMatrix, InMaskMatrix;
342             attribute vec4 InVertex;
343             varying highp vec2 OutTexCoordSource, OutTexCoordMask;
344             void main(void)
345             {
346                 OutTexCoordSource = vec2(InSourceMatrix * InVertex);
347                 OutTexCoordMask = vec2(InMaskMatrix * InVertex);
348                 gl_Position = InMatrix * InVertex;
349             }
350         );
351
352     const char* fragmentShaderSourceSimple =
353         FRAGMENT_SHADER(
354             uniform sampler2D SourceTexture;
355             uniform lowp float Opacity;
356             varying highp vec2 OutTexCoordSource;
357             void main(void)
358             {
359                 lowp vec4 color = texture2D(SourceTexture, OutTexCoordSource);
360                 gl_FragColor = vec4(color.rgb * Opacity, color.a * Opacity);
361             }
362         );
363
364     const char* vertexShaderSourceSimple =
365         VERTEX_SHADER(
366             uniform mat4 InMatrix, InSourceMatrix;
367             attribute vec4 InVertex;
368             varying highp vec2 OutTexCoordSource;
369             void main(void)
370             {
371                 OutTexCoordSource = vec2(InSourceMatrix * InVertex);
372                 gl_Position = InMatrix * InVertex;
373             }
374         );
375     const char* fragmentShaderSourceClip =
376         FRAGMENT_SHADER(
377             void main(void)
378             {
379                 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
380             }
381         );
382
383     const char* vertexShaderSourceClip =
384         VERTEX_SHADER(
385             uniform mat4 InMatrix;
386             attribute vec4 InVertex;
387             void main(void)
388             {
389                 gl_Position = InMatrix * InVertex;
390             }
391         );
392
393
394     TEXMAP_BUILD_SHADER(Simple)
395     TEXMAP_BUILD_SHADER(OpacityAndMask)
396     TEXMAP_BUILD_SHADER(Clip)
397
398     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, InMatrix)
399     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, InSourceMatrix)
400     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, InMaskMatrix)
401     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, SourceTexture)
402     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, MaskTexture)
403     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, Opacity)
404
405     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, InSourceMatrix)
406     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, InMatrix)
407     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, SourceTexture)
408     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, Opacity)
409
410     TEXMAP_GET_SHADER_VAR_LOCATION(Clip, InMatrix)
411 }
412
413 void TextureMapperGL::beginPainting()
414 {
415 #if PLATFORM(QT)
416     if (!initializeOpenGLShims())
417         return;
418
419     glGetIntegerv(GL_CURRENT_PROGRAM, &m_data->previousProgram);
420     if (m_context) {
421         QPainter* painter = m_context->platformContext();
422         painter->save();
423         painter->beginNativePainting();
424     }
425     glClearStencil(0);
426     glClear(GL_STENCIL_BUFFER_BIT);
427     bindSurface(0);
428 #endif
429     initializeShaders();
430 }
431
432 void TextureMapperGL::endPainting()
433 {
434 #if PLATFORM(QT)
435     glClearStencil(1);
436     glClear(GL_STENCIL_BUFFER_BIT);
437     glUseProgram(m_data->previousProgram);
438     if (!m_context)
439         return;
440     QPainter* painter = m_context->platformContext();
441     painter->endNativePainting();
442     painter->restore();
443 #endif
444 }
445
446
447 void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* mask)
448 {
449     if (!texture.isValid())
450         return;
451     const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
452     drawTexture(textureGL.id(), textureGL.isOpaque(), textureGL.relativeSize(), targetRect, matrix, opacity, mask, false);
453 }
454
455 void TextureMapperGL::drawTexture(uint32_t texture, bool opaque, const FloatSize& relativeSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, bool flip)
456 {
457     TextureMapperGLData::GlobalGLData::ShaderProgramIndex program;
458     if (maskTexture)
459         program = TextureMapperGLData::GlobalGLData::OpacityAndMaskProgram;
460     else
461         program = TextureMapperGLData::GlobalGLData::SimpleProgram;
462
463     const TextureMapperGLData::GlobalGLData::ProgramInfo& programInfo = data().globalGLData.programs[program];
464     GL_CMD(glUseProgram(programInfo.id))
465     data().currentProgram = program;
466     GL_CMD(glEnableVertexAttribArray(programInfo.vertexAttrib))
467     GL_CMD(glActiveTexture(GL_TEXTURE0))
468     GL_CMD(glBindTexture(GL_TEXTURE_2D, texture))
469     GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
470     const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
471     GL_CMD(glVertexAttribPointer(programInfo.vertexAttrib, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
472
473     TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
474             targetRect.width(), 0, 0, 0,
475             0, targetRect.height(), 0, 0,
476             0, 0, 1, 0,
477             targetRect.x(), targetRect.y(), 0, 1));
478
479     const GLfloat m4[] = {
480         matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
481         matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
482         matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
483         matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
484     };
485     const GLfloat m4src[] = {relativeSize.width(), 0, 0, 0,
486                                      0, relativeSize.height() * (flip ? -1 : 1), 0, 0,
487                                      0, 0, 1, 0,
488                                      0, flip ? relativeSize.height() : 0, 0, 1};
489
490     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::GlobalGLData::InMatrixVariable], 1, GL_FALSE, m4))
491     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::GlobalGLData::InSourceMatrixVariable], 1, GL_FALSE, m4src))
492     GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::GlobalGLData::SourceTextureVariable], 0))
493     GL_CMD(glUniform1f(programInfo.vars[TextureMapperGLData::GlobalGLData::OpacityVariable], opacity))
494
495     if (maskTexture && maskTexture->isValid()) {
496         const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture);
497         GL_CMD(glActiveTexture(GL_TEXTURE1))
498         GL_CMD(glBindTexture(GL_TEXTURE_2D, maskTextureGL->id()))
499         const GLfloat m4mask[] = {maskTextureGL->relativeSize().width(), 0, 0, 0,
500                                          0, maskTextureGL->relativeSize().height(), 0, 0,
501                                          0, 0, 1, 0,
502                                          0, 0, 0, 1};
503         GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::GlobalGLData::InMaskMatrixVariable], 1, GL_FALSE, m4mask));
504         GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::GlobalGLData::MaskTextureVariable], 1))
505         GL_CMD(glActiveTexture(GL_TEXTURE0))
506     }
507
508     if (opaque && opacity > 0.99 && !maskTexture)
509         GL_CMD(glDisable(GL_BLEND))
510     else {
511         GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA))
512         GL_CMD(glEnable(GL_BLEND))
513     }
514
515     GL_CMD(glDisable(GL_DEPTH_TEST))
516     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
517     GL_CMD(glDisableVertexAttribArray(programInfo.vertexAttrib))
518 }
519
520 const char* TextureMapperGL::type() const
521 {
522     return "OpenGL";
523 }
524
525 // This function is similar with GraphicsContext3D::texImage2DResourceSafe.
526 static void texImage2DResourceSafe(size_t width, size_t height)
527 {
528     const int pixelSize = 4; // RGBA
529     OwnArrayPtr<unsigned char> zero;
530     if (width && height) {
531         unsigned int size = width * height * pixelSize;
532         zero = adoptArrayPtr(new unsigned char[size]);
533         memset(zero.get(), 0, size);
534     }
535     GL_CMD(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, zero.get()))
536 }
537
538 void BitmapTextureGL::reset(const IntSize& newSize, bool opaque)
539 {
540     BitmapTexture::reset(newSize, opaque);
541     m_imageUID = 0;
542     IntSize newTextureSize = nextPowerOfTwo(newSize);
543     bool justCreated = false;
544     if (!m_id) {
545         GL_CMD(glGenTextures(1, &m_id))
546         justCreated = true;
547     }
548
549     if (justCreated || newTextureSize.width() > m_textureSize.width() || newTextureSize.height() > m_textureSize.height()) {
550         m_textureSize = newTextureSize;
551         GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
552         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR))
553         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR))
554         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE))
555         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE))
556         texImage2DResourceSafe(m_textureSize.width(), m_textureSize.height());
557     }
558     m_actualSize = newSize;
559     m_relativeSize = FloatSize(float(newSize.width()) / m_textureSize.width(), float(newSize.height()) / m_textureSize.height());
560     m_opaque = opaque;
561     m_surfaceNeedsReset = true;
562 }
563
564 PlatformGraphicsContext* BitmapTextureGL::beginPaint(const IntRect& dirtyRect)
565 {
566     m_buffer = BGRA32PremultimpliedBuffer::create();
567     m_dirtyRect = dirtyRect;
568     return m_buffer->beginPaint(dirtyRect, m_opaque);
569 }
570
571 void BitmapTextureGL::endPaint()
572 {
573     if (!m_buffer)
574         return;
575     m_buffer->endPaint();
576     updateContents(BGRAFormat, m_dirtyRect, m_buffer->data());
577     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
578     m_buffer.clear();
579 }
580
581 #ifdef TEXMAP_OPENGL_ES_2
582 static void swizzleBGRAToRGBA(uint32_t* data, const IntSize& size)
583 {
584     int width = size.width();
585     int height = size.height();
586     for (int y = 0; y < height; ++y) {
587         uint32_t* p = data + y * width;
588         for (int x = 0; x < width; ++x)
589             p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
590     }
591 }
592 #endif
593
594 void BitmapTextureGL::updateContents(PixelFormat pixelFormat, const IntRect& rect, void* bits)
595 {
596     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
597 #ifdef TEXMAP_OPENGL_ES_2
598     bool shouldSwizzle = false;
599 #endif
600
601     GLint glFormat = GL_RGBA;
602     switch (pixelFormat) {
603     case RGBAFormat:
604         glFormat = GL_RGBA;
605         break;
606     case RGBFormat:
607         glFormat = GL_RGB;
608         break;
609     case BGRAFormat:
610 #ifdef TEXMAP_OPENGL_ES_2
611         shouldSwizzle = true;
612         glFormat = GL_RGBA;
613 #else
614         glFormat = GL_BGRA;
615 #endif
616         break;
617     case BGRFormat:
618 #ifdef TEXMAP_OPENGL_ES_2
619         shouldSwizzle = true;
620         glFormat = GL_RGB;
621 #else
622         glFormat = GL_BGR;
623 #endif
624          break;
625     }
626
627 #ifdef TEXMAP_OPENGL_ES_2
628     if (shouldSwizzle)
629         swizzleBGRAToRGBA(static_cast<uint32_t*>(bits), rect.size());
630 #endif
631     GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), glFormat, GL_UNSIGNED_BYTE, bits))
632 }
633
634 void BitmapTextureGL::setContentsToImage(Image* image)
635 {
636     ImageUID uid = image ? uidForImage(image) : 0;
637     if (!image || !uid) {
638         if (m_imageUID)
639             destroy();
640         return;
641     }
642
643     if (uid == m_imageUID)
644         return;
645     bool found = false;
646     GLuint newTextureID = m_textureMapper->data().directlyCompositedImages.findOrCreate(uid, found);
647     if (newTextureID != m_id) {
648         m_imageUID = uid;
649         destroy();
650         m_id = newTextureID;
651         reset(image->size(), false);
652         if (!found) {
653             GraphicsContext context(beginPaint(IntRect(0, 0, m_textureSize.width(), m_textureSize.height())));
654             context.drawImage(image, ColorSpaceDeviceRGB, IntPoint(0, 0), CompositeCopy);
655             endPaint();
656         }
657     }
658 }
659
660 static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool flip)
661 {
662     const float near = 9999999;
663     const float far = -99999;
664
665     return TransformationMatrix(2.0 / float(size.width()), 0, 0, 0,
666                                 0, (flip ? -2.0 : 2.0) / float(size.height()), 0, 0,
667                                 0, 0, -2.f / (far - near), 0,
668                                 -1, flip ? 1 : -1, -(far + near) / (far - near), 1);
669 }
670
671 void BitmapTextureGL::bind()
672 {
673     int& stencilIndex = TextureMapperGLData::globalGLData.stencilIndex;
674     if (m_surfaceNeedsReset || !m_fbo) {
675         if (!m_fbo)
676             GL_CMD(glGenFramebuffers(1, &m_fbo))
677         if (!m_rbo)
678             GL_CMD(glGenRenderbuffers(1, &m_rbo));
679         GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo))
680 #ifdef TEXMAP_OPENGL_ES_2
681         GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()))
682 #else
683         GL_CMD(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()))
684 #endif
685         GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo))
686         GL_CMD(glBindTexture(GL_TEXTURE_2D, 0))
687         GL_CMD(glBindRenderbuffer(GL_RENDERBUFFER, 0))
688         GL_CMD(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id(), 0))
689         GL_CMD(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo))
690 #ifndef TEXMAP_OPENGL_ES_2
691         GL_CMD(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo));
692 #endif
693         GL_CMD(glClearColor(0, 0, 0, 0))
694         GL_CMD(glClearStencil(stencilIndex - 1))
695         GL_CMD(glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))
696         m_surfaceNeedsReset = false;
697     } else
698         GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo))
699
700     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
701     glStencilFunc(stencilIndex > 1 ? GL_GEQUAL : GL_ALWAYS, stencilIndex - 1, stencilIndex - 1);
702     GL_CMD(glViewport(0, 0, size().width(), size().height()))
703     m_textureMapper->data().projectionMatrix = createProjectionMatrix(size(), false);
704     glDisable(GL_SCISSOR_TEST);
705 }
706
707 void BitmapTextureGL::destroy()
708 {
709     if (m_id && (!m_imageUID || !m_textureMapper->data().directlyCompositedImages.deref(m_imageUID)))
710         GL_CMD(glDeleteTextures(1, &m_id))
711
712     if (m_fbo)
713         GL_CMD(glDeleteFramebuffers(1, &m_fbo))
714
715     if (m_rbo)
716         GL_CMD(glDeleteRenderbuffers(1, &m_rbo))
717
718     m_fbo = 0;
719     m_id = 0;
720     m_textureSize = IntSize();
721     m_relativeSize = FloatSize(1, 1);
722 }
723
724 bool BitmapTextureGL::isValid() const
725 {
726     return m_id;
727 }
728
729 IntSize BitmapTextureGL::size() const
730 {
731     return m_textureSize;
732 }
733
734 TextureMapperGL::~TextureMapperGL()
735 {
736     delete m_data;
737 }
738
739 void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer)
740 {
741     BitmapTextureGL* surface = static_cast<BitmapTextureGL*>(surfacePointer);
742
743     if (!surface) {
744         GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0))
745         data().projectionMatrix = createProjectionMatrix(viewportSize(), true).multiply(transform());
746         GL_CMD(glStencilFunc(data().globalGLData.stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().globalGLData.stencilIndex - 1, data().globalGLData.stencilIndex - 1))
747         GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP))
748         GL_CMD(glViewport(0, 0, viewportSize().width(), viewportSize().height()))
749         return;
750     }
751
752     surface->bind();
753 }
754
755 void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
756 {
757     TextureMapperGLData::GlobalGLData::ShaderProgramIndex program = TextureMapperGLData::GlobalGLData::ClipProgram;
758     const TextureMapperGLData::GlobalGLData::ProgramInfo& programInfo = data().globalGLData.programs[program];
759     GL_CMD(glUseProgram(programInfo.id))
760     GL_CMD(glEnableVertexAttribArray(programInfo.vertexAttrib))
761     const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
762     GL_CMD(glVertexAttribPointer(programInfo.vertexAttrib, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
763
764     TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix)
765             .multiply(modelViewMatrix)
766             .multiply(TransformationMatrix(targetRect.width(), 0, 0, 0,
767                 0, targetRect.height(), 0, 0,
768                 0, 0, 1, 0,
769                 targetRect.x(), targetRect.y(), 0, 1));
770
771     const GLfloat m4[] = {
772         matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
773         matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
774         matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
775         matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
776     };
777
778     int& stencilIndex = data().globalGLData.stencilIndex;
779
780     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::GlobalGLData::InMatrixVariable], 1, GL_FALSE, m4))
781     GL_CMD(glEnable(GL_STENCIL_TEST))
782     GL_CMD(glStencilFunc(GL_NEVER, stencilIndex, stencilIndex))
783     GL_CMD(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE))
784     GL_CMD(glStencilMask(0xff & ~(stencilIndex - 1)))
785     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
786     GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP))
787     stencilIndex <<= 1;
788     glStencilFunc(stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, stencilIndex - 1, stencilIndex - 1);
789     GL_CMD(glDisableVertexAttribArray(programInfo.vertexAttrib))
790 }
791
792 void TextureMapperGL::endClip()
793 {
794     data().globalGLData.stencilIndex >>= 1;
795     glStencilFunc(data().globalGLData.stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().globalGLData.stencilIndex - 1, data().globalGLData.stencilIndex - 1);
796 }
797
798 PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
799 {
800     BitmapTextureGL* texture = new BitmapTextureGL();
801     texture->setTextureMapper(this);
802     return adoptRef(texture);
803 }
804
805 };