• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Timer.h"
26 #include <wtf/HashMap.h>
27 #include <wtf/PassRefPtr.h>
28 #include <wtf/RefCounted.h>
29 
30 #if defined(TEXMAP_OPENGL_ES_2)
31 #include <GLES2/gl2.h>
32 #elif OS(MAC_OS_X)
33 #include <AGL/agl.h>
34 #include <gl.h>
35 #else
36 #if OS(UNIX)
37 #include <GL/glx.h>
38 #endif
39 #include <GL/gl.h>
40 #endif
41 
42 #ifndef TEXMAP_OPENGL_ES2
43 extern "C" {
44     void glUniform1f(GLint, GLfloat);
45     void glUniform1i(GLint, GLint);
46     void glVertexAttribPointer(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
47     void glUniform4f(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
48     void glShaderSource(GLuint, GLsizei, const char**, const GLint*);
49     GLuint glCreateShader(GLenum);
50     void glShaderSource(GLuint, GLsizei, const char**, const GLint*);
51     void glCompileShader(GLuint);
52     void glDeleteShader(GLuint);
53     void glUniformMatrix4fv(GLint, GLsizei, GLboolean, const GLfloat*);
54     GLuint glCreateProgram();
55     void glAttachShader(GLuint, GLuint);
56     void glLinkProgram(GLuint);
57     void glUseProgram(GLuint);
58     void glDisableVertexAttribArray(GLuint);
59     void glEnableVertexAttribArray(GLuint);
60     void glBindFramebuffer(GLenum target, GLuint framebuffer);
61     void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
62     void glGenFramebuffers(GLsizei n, GLuint* framebuffers);
63     void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
64     void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
65     void glBindBuffer(GLenum, GLuint);
66     void glDeleteBuffers(GLsizei, const GLuint*);
67     void glGenBuffers(GLsizei, GLuint*);
68     void glBufferData(GLenum, GLsizeiptr, const GLvoid*, GLenum);
69     void glBufferSubData(GLenum, GLsizeiptr, GLsizeiptr, const GLvoid*);
70     void glGetProgramInfoLog(GLuint program, GLsizei, GLsizei*, GLchar*);
71 
72 #if !OS(MAC_OS_X)
73     GLint glGetUniformLocation(GLuint, const GLchar*);
74     GLint glBindAttribLocation(GLuint, GLuint, const GLchar*);
75 #endif
76 }
77 #endif
78 
79 namespace WebCore {
80 
debugGLCommand(const char * command,int line)81 inline static void debugGLCommand(const char* command, int line)
82 {
83     const GLenum err = glGetError();
84     if (!err)
85         return;
86     WTFReportError(__FILE__, line, WTF_PRETTY_FUNCTION, "[TextureMapper GL] Command failed: %s (%x)\n", command, err);
87 }
88 
89 #define DEBUG_GL_COMMANDS
90 
91 #ifdef DEBUG_GL_COMMANDS
92 #define GL_CMD(x) {x, debugGLCommand(#x, __LINE__); }
93 #else
94 #define GL_CMD(x) x
95 #endif
96 
97 static const GLuint gInVertexAttributeIndex = 0;
98 
99 struct TextureMapperGLData {
100     static struct ShaderInfo {
101         enum ShaderProgramIndex {
102             SimpleProgram,
103             OpacityAndMaskProgram,
104             TargetProgram,
105 
106             ProgramCount
107         };
108 
109         enum ShaderVariableIndex {
110             InMatrixVariable,
111             InSourceMatrixVariable,
112             InMaskMatrixVariable,
113             OpacityVariable,
114             SourceTextureVariable,
115             MaskTextureVariable,
116 
117             VariableCount
118         };
119 
120         struct ProgramInfo {
121             GLuint id;
122             GLint vars[VariableCount];
123         };
124 
getUniformLocationWebCore::TextureMapperGLData::ShaderInfo125         GLint getUniformLocation(ShaderProgramIndex prog, ShaderVariableIndex var, const char* name)
126         {
127             return programs[prog].vars[var] = glGetUniformLocation(programs[prog].id, name);
128         }
129 
createShaderProgramWebCore::TextureMapperGLData::ShaderInfo130         void createShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource, ShaderProgramIndex index)
131         {
132             GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
133             GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
134             GL_CMD(glShaderSource(vertexShader, 1, &vertexShaderSource, 0))
135             GL_CMD(glShaderSource(fragmentShader, 1, &fragmentShaderSource, 0))
136             GLuint programID = glCreateProgram();
137             GL_CMD(glCompileShader(vertexShader))
138             GL_CMD(glCompileShader(fragmentShader))
139             GL_CMD(glAttachShader(programID, vertexShader))
140             GL_CMD(glAttachShader(programID, fragmentShader))
141             GL_CMD(glBindAttribLocation(programID, gInVertexAttributeIndex, "InVertex"))
142             GL_CMD(glLinkProgram(programID))
143             programs[index].id = programID;
144 #ifdef PRINT_PROGRAM_INFO_LOG
145             char infoLog[1024];
146             int len;
147             GL_CMD(glGetProgramInfoLog(programID, 1024, &len, infoLog));
148             LOG(Graphics, "Compiled program for texture mapper. Log: %s\n", infoLog);
149 #endif
150         }
151 
152         ProgramInfo programs[ProgramCount];
153 
154     } shaderInfo;
155 
156     struct DirectlyCompositedImageRepository {
157         struct Entry {
158             GLuint texture;
159             int refCount;
160         };
161         HashMap<NativeImagePtr, Entry> imageToTexture;
162 
findOrCreateWebCore::TextureMapperGLData::DirectlyCompositedImageRepository163         GLuint findOrCreate(NativeImagePtr image, bool& found)
164         {
165             HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.find(image);
166             found = false;
167             if (it != imageToTexture.end()) {
168                 it->second.refCount++;
169                 found = true;
170                 return it->second.texture;
171             }
172             Entry entry;
173             GL_CMD(glGenTextures(1, &entry.texture));
174             entry.refCount = 1;
175             imageToTexture.add(image, entry);
176             return entry.texture;
177         }
178 
derefWebCore::TextureMapperGLData::DirectlyCompositedImageRepository179         bool deref(NativeImagePtr image)
180         {
181             HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.find(image);
182             if (it != imageToTexture.end()) {
183                 if (it->second.refCount < 2) {
184                     imageToTexture.remove(it);
185                     return false;
186                 }
187             }
188             return true;
189         }
190 
DirectlyCompositedImageRepositoryWebCore::TextureMapperGLData::DirectlyCompositedImageRepository191         DirectlyCompositedImageRepository()
192         {
193         }
194 
~DirectlyCompositedImageRepositoryWebCore::TextureMapperGLData::DirectlyCompositedImageRepository195         ~DirectlyCompositedImageRepository()
196         {
197             for (HashMap<NativeImagePtr, Entry>::iterator it = imageToTexture.begin(); it != imageToTexture.end(); ++it) {
198                 GLuint texture = it->second.texture;
199                 if (texture)
200                     GL_CMD(glDeleteTextures(1, &texture));
201             }
202 
203         }
204     } directlyCompositedImages;
205 
TextureMapperGLDataWebCore::TextureMapperGLData206     TextureMapperGLData()
207         : currentProgram(TextureMapperGLData::ShaderInfo::TargetProgram)
208     { }
209 
210     TransformationMatrix projectionMatrix;
211     int currentProgram;
212 
213 #if OS(MAC_OS_X)
214     AGLContext aglContext;
215 #elif OS(UNIX)
216     Drawable glxDrawable;
217     GLXContext glxContext;
218 #endif
219 };
220 
221 TextureMapperGLData::ShaderInfo TextureMapperGLData::shaderInfo;
222 
223 class BitmapTextureGL : public BitmapTexture {
224 public:
225     virtual void destroy();
226     virtual IntSize size() const;
227     virtual bool isValid() const;
228     virtual void reset(const IntSize&, bool opaque);
229     virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect);
230     virtual void endPaint();
231     virtual void setContentsToImage(Image*);
~BitmapTextureGL()232     ~BitmapTextureGL() { destroy(); }
233 
234 private:
235     GLuint m_id;
236     NativeImagePtr m_image;
237     FloatSize m_relativeSize;
238     bool m_opaque;
239     IntSize m_textureSize;
240     RefPtr<RGBA32PremultimpliedBuffer> m_buffer;
241     IntRect m_dirtyRect;
242     GLuint m_fbo;
243     IntSize m_actualSize;
244     bool m_surfaceNeedsReset;
245     TextureMapperGL* m_textureMapper;
BitmapTextureGL()246     BitmapTextureGL()
247         : m_id(0)
248         , m_image(0)
249         , m_opaque(false)
250         , m_fbo(0)
251         , m_surfaceNeedsReset(true)
252         , m_textureMapper(0)
253     {
254     }
255 
256     friend class TextureMapperGL;
257 };
258 
259 #define TEXMAP_GET_SHADER_VAR_LOCATION(prog, var) \
260     if (TextureMapperGLData::shaderInfo.getUniformLocation(TextureMapperGLData::shaderInfo.prog##Program, TextureMapperGLData::shaderInfo.var##Variable, #var) < 0) \
261             LOG_ERROR("Couldn't find variable "#var" in program "#prog"\n");
262 
263 #define TEXMAP_BUILD_SHADER(program) \
264     TextureMapperGLData::shaderInfo.createShaderProgram(vertexShaderSource##program, fragmentShaderSource##program, TextureMapperGLData::shaderInfo.program##Program);
265 
TextureMapperGL()266 TextureMapperGL::TextureMapperGL()
267     : m_data(new TextureMapperGLData)
268 {
269     static bool shadersCompiled = false;
270     obtainCurrentContext();
271     if (shadersCompiled)
272         return;
273     shadersCompiled = true;
274 #ifndef TEXMAP_OPENGL_ES2
275 #define OES2_PRECISION_DEFINITIONS \
276     "#define lowp\n#define highp\n"
277 #else
278 #define OES2_PRECISION_DEFINITIONS
279 #endif
280 
281     const char* fragmentShaderSourceOpacityAndMask =
282             OES2_PRECISION_DEFINITIONS
283 "               uniform sampler2D SourceTexture, MaskTexture;                       \n"
284 "               uniform lowp float Opacity;                                         \n"
285 "               varying highp vec2 OutTexCoordSource, OutTexCoordMask;              \n"
286 "               void main(void)                                                     \n"
287 "               {                                                                   \n"
288 "                   lowp vec4 color = texture2D(SourceTexture, OutTexCoordSource);  \n"
289 "                   lowp vec4 maskColor = texture2D(MaskTexture, OutTexCoordMask);  \n"
290 "                   lowp float o = Opacity * maskColor.a;                           \n"
291 "                   gl_FragColor = vec4(color.rgb * o, color.a * o);                \n"
292 "               }                                                                   \n";
293 
294     const char* vertexShaderSourceOpacityAndMask =
295             OES2_PRECISION_DEFINITIONS
296 "               uniform mat4 InMatrix, InSourceMatrix, InMaskMatrix;            \n"
297 "               attribute vec4 InVertex;                                        \n"
298 "               varying highp vec2 OutTexCoordSource, OutTexCoordMask;          \n"
299 "               void main(void)                                                 \n"
300 "               {                                                               \n"
301 "                   OutTexCoordSource = vec2(InSourceMatrix * InVertex);        \n"
302 "                   OutTexCoordMask = vec2(InMaskMatrix * InVertex);            \n"
303 "                   gl_Position = InMatrix * InVertex;                          \n"
304 "               }                                                               \n";
305 
306     const char* fragmentShaderSourceSimple =
307             OES2_PRECISION_DEFINITIONS
308 "               uniform sampler2D SourceTexture;                                    \n"
309 "               uniform lowp float Opacity;                                         \n"
310 "               varying highp vec2 OutTexCoordSource;                               \n"
311 "               void main(void)                                                     \n"
312 "               {                                                                   \n"
313 "                   lowp vec4 color = texture2D(SourceTexture, OutTexCoordSource);  \n"
314 "                   gl_FragColor = vec4(color.rgb * Opacity, color.a * Opacity);    \n"
315 "               }                                                                   \n";
316 
317     const char* vertexShaderSourceSimple =
318             OES2_PRECISION_DEFINITIONS
319 "               uniform mat4 InMatrix, InSourceMatrix;                      \n"
320 "               attribute vec4 InVertex;                                    \n"
321 "               varying highp vec2 OutTexCoordSource;                       \n"
322 "               void main(void)                                             \n"
323 "               {                                                           \n"
324 "                   OutTexCoordSource = vec2(InSourceMatrix * InVertex);    \n"
325 "                   gl_Position = InMatrix * InVertex;                      \n"
326 "               }                                                           \n";
327 
328     const char* fragmentShaderSourceTarget =
329             OES2_PRECISION_DEFINITIONS
330 "               uniform sampler2D SourceTexture;                                            \n"
331 "               uniform lowp float Opacity;                                                 \n"
332 "               varying highp vec2 OutTexCoordSource;                                       \n"
333 "               void main(void)                                                             \n"
334 "               {                                                                           \n"
335 "                   lowp vec4 color = texture2D(SourceTexture, OutTexCoordSource);          \n"
336 "                   gl_FragColor = vec4(color.bgr * Opacity, color.a * Opacity);            \n"
337 "               }                                                                           \n";
338 
339     const char* vertexShaderSourceTarget = vertexShaderSourceSimple;
340 
341     TEXMAP_BUILD_SHADER(Simple)
342     TEXMAP_BUILD_SHADER(OpacityAndMask)
343     TEXMAP_BUILD_SHADER(Target)
344 
345     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, InMatrix)
346     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, InSourceMatrix)
347     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, InMaskMatrix)
348     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, SourceTexture)
349     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, MaskTexture)
350     TEXMAP_GET_SHADER_VAR_LOCATION(OpacityAndMask, Opacity)
351 
352     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, InSourceMatrix)
353     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, InMatrix)
354     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, SourceTexture)
355     TEXMAP_GET_SHADER_VAR_LOCATION(Simple, Opacity)
356 
357     TEXMAP_GET_SHADER_VAR_LOCATION(Target, InSourceMatrix)
358     TEXMAP_GET_SHADER_VAR_LOCATION(Target, InMatrix)
359     TEXMAP_GET_SHADER_VAR_LOCATION(Target, SourceTexture)
360     TEXMAP_GET_SHADER_VAR_LOCATION(Target, Opacity)
361 }
362 
drawTexture(const BitmapTexture & texture,const IntRect & targetRect,const TransformationMatrix & modelViewMatrix,float opacity,const BitmapTexture * maskTexture)363 void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture)
364 {
365     if (!texture.isValid())
366         return;
367 
368     const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
369 
370     TextureMapperGLData::ShaderInfo::ShaderProgramIndex program;
371     if (maskTexture)
372         program = TextureMapperGLData::ShaderInfo::OpacityAndMaskProgram;
373     else
374         program = TextureMapperGLData::ShaderInfo::SimpleProgram;
375 
376     const TextureMapperGLData::ShaderInfo::ProgramInfo& programInfo = data().shaderInfo.programs[program];
377     if (data().currentProgram != program) {
378         GL_CMD(glUseProgram(programInfo.id))
379         GL_CMD(glDisableVertexAttribArray(gInVertexAttributeIndex))
380         data().currentProgram = program;
381         GL_CMD(glEnableVertexAttribArray(gInVertexAttributeIndex))
382     }
383 
384     GL_CMD(glDisable(GL_DEPTH_TEST))
385     GL_CMD(glDisable(GL_STENCIL_TEST))
386 
387     GL_CMD(glActiveTexture(GL_TEXTURE0))
388     GL_CMD(glBindTexture(GL_TEXTURE_2D, textureGL.m_id))
389     GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
390     const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
391     GL_CMD(glVertexAttribPointer(gInVertexAttributeIndex, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
392 
393     TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
394             targetRect.width(), 0, 0, 0,
395             0, targetRect.height(), 0, 0,
396             0, 0, 1, 0,
397             targetRect.x(), targetRect.y(), 0, 1));
398 
399     const GLfloat m4[] = {
400         matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
401         matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
402         matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
403         matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
404     };
405     const GLfloat m4src[] = {textureGL.m_relativeSize.width(), 0, 0, 0,
406                                      0, textureGL.m_relativeSize.height(), 0, 0,
407                                      0, 0, 1, 0,
408                                      0, 0, 0, 1};
409     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InMatrixVariable], 1, GL_FALSE, m4))
410     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src))
411     GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::ShaderInfo::SourceTextureVariable], 0))
412     GL_CMD(glUniform1f(programInfo.vars[TextureMapperGLData::ShaderInfo::OpacityVariable], opacity))
413 
414     if (maskTexture && maskTexture->isValid()) {
415         const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture);
416         GL_CMD(glActiveTexture(GL_TEXTURE1))
417         GL_CMD(glBindTexture(GL_TEXTURE_2D, maskTextureGL->m_id))
418         const GLfloat m4mask[] = {maskTextureGL->m_relativeSize.width(), 0, 0, 0,
419                                          0, maskTextureGL->m_relativeSize.height(), 0, 0,
420                                          0, 0, 1, 0,
421                                          0, 0, 0, 1};
422         GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InMaskMatrixVariable], 1, GL_FALSE, m4mask));
423         GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::ShaderInfo::MaskTextureVariable], 1))
424         GL_CMD(glActiveTexture(GL_TEXTURE0))
425     }
426 
427     if (textureGL.m_opaque && opacity > 0.99 && !maskTexture)
428         GL_CMD(glDisable(GL_BLEND))
429     else {
430         GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA))
431         GL_CMD(glEnable(GL_BLEND))
432     }
433 
434     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
435 }
436 
type() const437 const char* TextureMapperGL::type() const
438 {
439     return "OpenGL";
440 }
441 
reset(const IntSize & newSize,bool opaque)442 void BitmapTextureGL::reset(const IntSize& newSize, bool opaque)
443 {
444     BitmapTexture::reset(newSize, opaque);
445     m_image = 0;
446     IntSize newTextureSize = nextPowerOfTwo(newSize);
447     bool justCreated = false;
448     if (!m_id) {
449         GL_CMD(glGenTextures(1, &m_id))
450         justCreated = true;
451     }
452 
453     if (justCreated || newTextureSize.width() > m_textureSize.width() || newTextureSize.height() > m_textureSize.height()) {
454         m_textureSize = newTextureSize;
455         GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
456         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR))
457         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR))
458         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE))
459         GL_CMD(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE))
460         GL_CMD(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_textureSize.width(), m_textureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0))
461     }
462     m_actualSize = newSize;
463     m_relativeSize = FloatSize(float(newSize.width()) / m_textureSize.width(), float(newSize.height()) / m_textureSize.height());
464     m_opaque = opaque;
465     m_surfaceNeedsReset = true;
466 }
467 
beginPaint(const IntRect & dirtyRect)468 PlatformGraphicsContext* BitmapTextureGL::beginPaint(const IntRect& dirtyRect)
469 {
470     m_buffer = RGBA32PremultimpliedBuffer::create();
471     m_dirtyRect = dirtyRect;
472     return m_buffer->beginPaint(dirtyRect, m_opaque);
473 }
474 
endPaint()475 void BitmapTextureGL::endPaint()
476 {
477     if (!m_buffer)
478         return;
479     m_buffer->endPaint();
480     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
481     GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirtyRect.x(), m_dirtyRect.y(), m_dirtyRect.width(), m_dirtyRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, m_buffer->data()))
482     m_buffer.clear();
483 }
484 
setContentsToImage(Image * image)485 void BitmapTextureGL::setContentsToImage(Image* image)
486 {
487     NativeImagePtr nativeImage = image ? image->nativeImageForCurrentFrame() : 0;
488     if (!image || !nativeImage) {
489         if (m_image)
490             destroy();
491         return;
492     }
493 
494     if (nativeImage == m_image)
495         return;
496     bool found = false;
497     GLuint newTextureID = m_textureMapper->data().directlyCompositedImages.findOrCreate(nativeImage, found);
498     if (newTextureID != m_id) {
499         destroy();
500         m_id = newTextureID;
501         reset(image->size(), false);
502         m_image = nativeImage;
503         if (!found) {
504             GraphicsContext context(beginPaint(IntRect(0, 0, m_textureSize.width(), m_textureSize.height())));
505             context.drawImage(image, ColorSpaceDeviceRGB, IntPoint(0, 0), CompositeCopy);
506             endPaint();
507         }
508     }
509 }
510 
destroy()511 void BitmapTextureGL::destroy()
512 {
513     if (m_id && (!m_image || !m_textureMapper->data().directlyCompositedImages.deref(m_image)))
514         GL_CMD(glDeleteTextures(1, &m_id))
515     if (m_fbo)
516         GL_CMD(glDeleteFramebuffers(1, &m_fbo))
517 
518     m_fbo = 0;
519     m_id = 0;
520     m_textureSize = IntSize();
521     m_relativeSize = FloatSize(1, 1);
522 }
523 
isValid() const524 bool BitmapTextureGL::isValid() const
525 {
526     return m_id;
527 }
528 
size() const529 IntSize BitmapTextureGL::size() const
530 {
531     return m_textureSize;
532 }
533 
createProjectionMatrix(const IntSize & size,bool flip)534 static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool flip)
535 {
536     return TransformationMatrix(2.0 / float(size.width()), 0, 0, 0,
537                                 0, (flip ? -2.0 : 2.0) / float(size.height()), 0, 0,
538                                 0, 0, -0.000001, 0,
539                                 -1, flip ? 1 : -1, 0, 1);
540 }
541 
~TextureMapperGL()542 TextureMapperGL::~TextureMapperGL()
543 {
544     makeContextCurrent();
545     delete m_data;
546 }
547 
makeContextCurrent()548 bool TextureMapperGL::makeContextCurrent()
549 {
550 #if OS(MAC_OS_X)
551     return aglSetCurrentContext(data().aglContext);
552 #elif OS(UNIX)
553     Display* display = XOpenDisplay(0);
554     if (!display)
555         return false;
556     return glXMakeCurrent(display, data().glxDrawable, data().glxContext);
557 #endif
558 }
559 
obtainCurrentContext()560 void TextureMapperGL::obtainCurrentContext()
561 {
562 #if OS(MAC_OS_X)
563     data().aglContext = aglGetCurrentContext();
564 #elif OS(UNIX)
565     data().glxDrawable = glXGetCurrentDrawable();
566     data().glxContext = glXGetCurrentContext();
567 #endif
568 }
569 
bindSurface(BitmapTexture * surfacePointer)570 void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer)
571 {
572     BitmapTextureGL* surface = static_cast<BitmapTextureGL*>(surfacePointer);
573 
574     if (!surface)
575         return;
576 
577     TransformationMatrix matrix = createProjectionMatrix(surface->size(), false);
578     matrix.translate(-surface->offset().x(), -surface->offset().y());
579 
580     if (surface->m_surfaceNeedsReset || !surface->m_fbo) {
581         if (!surface->m_fbo)
582             GL_CMD(glGenFramebuffers(1, &surface->m_fbo))
583         GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, surface->m_fbo))
584         GL_CMD(glBindTexture(GL_TEXTURE_2D, 0))
585         GL_CMD(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, surface->m_id, 0))
586         GL_CMD(glClearColor(0, 0, 0, 0))
587         GL_CMD(glClear(GL_COLOR_BUFFER_BIT))
588         surface->m_surfaceNeedsReset = false;
589     } else {
590         GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, surface->m_fbo))
591     }
592 
593     GL_CMD(glViewport(0, 0, surface->size().width(), surface->size().height()))
594     data().projectionMatrix = matrix;
595 }
596 
setClip(const IntRect & rect)597 void TextureMapperGL::setClip(const IntRect& rect)
598 {
599     GL_CMD(glScissor(rect.x(), rect.y(), rect.width(), rect.height()))
600     GL_CMD(glEnable(GL_SCISSOR_TEST))
601 }
602 
603 
paintToTarget(const BitmapTexture & aSurface,const IntSize & surfaceSize,const TransformationMatrix & transform,float opacity,const IntRect & visibleRect)604 void TextureMapperGL::paintToTarget(const BitmapTexture& aSurface, const IntSize& surfaceSize, const TransformationMatrix& transform, float opacity, const IntRect& visibleRect)
605 {
606     const BitmapTextureGL& surface = static_cast<const BitmapTextureGL&>(aSurface);
607 
608     // Create the model-view-projection matrix to display on screen.
609     TransformationMatrix matrix = createProjectionMatrix(surfaceSize, true).multiply(transform).multiply(
610                 TransformationMatrix(
611                         surface.m_actualSize.width(), 0, 0, 0,
612                         0, surface.m_actualSize.height(), 0, 0,
613                         0, 0, 1, 0,
614                         surface.offset().x(), surface.offset().y(), 0, 1)
615             );
616 
617     const GLfloat m4[] = {
618         matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
619         matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
620         matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
621         matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
622     };
623 
624     const GLfloat m4src[] = {surface.m_relativeSize.width(), 0, 0, 0,
625                                      0, surface.m_relativeSize.height(), 0, 0,
626                                      0, 0, 1, 0,
627                                      0, 0, 0, 1};
628 
629     // We already blended the alpha in; the result is premultiplied.
630     GL_CMD(glUseProgram(data().shaderInfo.programs[TextureMapperGLData::ShaderInfo::TargetProgram].id))
631     GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0))
632     GL_CMD(glViewport(0, 0, surfaceSize.width(), surfaceSize.height()))
633     GL_CMD(glDisable(GL_STENCIL_TEST))
634     const TextureMapperGLData::ShaderInfo::ProgramInfo& programInfo = data().shaderInfo.programs[TextureMapperGLData::ShaderInfo::TargetProgram];
635     GL_CMD(glUniform1f(programInfo.vars[TextureMapperGLData::ShaderInfo::OpacityVariable], opacity))
636     GL_CMD(glActiveTexture(GL_TEXTURE0))
637     GL_CMD(glBindTexture(GL_TEXTURE_2D, surface.m_id))
638     GL_CMD(glUniform1i(programInfo.vars[TextureMapperGLData::ShaderInfo::SourceTextureVariable], 0))
639     GL_CMD(glEnableVertexAttribArray(gInVertexAttributeIndex))
640     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InMatrixVariable], 1, GL_FALSE, m4))
641     GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src))
642     GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
643     const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
644     GL_CMD(glVertexAttribPointer(gInVertexAttributeIndex, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
645     GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA))
646     GL_CMD(glEnable(GL_BLEND))
647     setClip(visibleRect);
648 
649     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
650     GL_CMD(glDisableVertexAttribArray(0))
651     GL_CMD(glUseProgram(0))
652     GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
653     data().currentProgram = TextureMapperGLData::ShaderInfo::TargetProgram;
654 }
655 
createTexture()656 PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
657 {
658     BitmapTextureGL* texture = new BitmapTextureGL();
659     texture->m_textureMapper = this;
660     return adoptRef(texture);
661 }
662 
663 };
664