Home | History | Annotate | Download | only in opengl
      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 
     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 
    125         GLint getUniformLocation(ShaderProgramIndex prog, ShaderVariableIndex var, const char* name)
    126         {
    127             return programs[prog].vars[var] = glGetUniformLocation(programs[prog].id, name);
    128         }
    129 
    130         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 
    163         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 
    179         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 
    191         DirectlyCompositedImageRepository()
    192         {
    193         }
    194 
    195         ~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 
    206     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*);
    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;
    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 
    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 
    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 
    437 const char* TextureMapperGL::type() const
    438 {
    439     return "OpenGL";
    440 }
    441 
    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 
    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 
    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 
    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 
    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 
    524 bool BitmapTextureGL::isValid() const
    525 {
    526     return m_id;
    527 }
    528 
    529 IntSize BitmapTextureGL::size() const
    530 {
    531     return m_textureSize;
    532 }
    533 
    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 
    542 TextureMapperGL::~TextureMapperGL()
    543 {
    544     makeContextCurrent();
    545     delete m_data;
    546 }
    547 
    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 
    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 
    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 
    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 
    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 
    656 PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
    657 {
    658     BitmapTextureGL* texture = new BitmapTextureGL();
    659     texture->m_textureMapper = this;
    660     return adoptRef(texture);
    661 }
    662 
    663 };
    664