blob: f3e93d9741e39b4a33eb8fbd48970dc1f42c0ab5 [file] [log] [blame]
/*
Copyright (C) 2010 Tieto Corporation.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "GraphicsContext3D.h"
#include "CString.h"
#include "CanvasObject.h"
#include "GraphicsContext.h"
#include "HTMLCanvasElement.h"
#include "ImageBuffer.h"
#include "NotImplemented.h"
#include "WebGLActiveInfo.h"
#include "WebGLArray.h"
#include "WebGLBuffer.h"
#include "WebGLFloatArray.h"
#include "WebGLFramebuffer.h"
#include "WebGLIntArray.h"
#include "WebGLProgram.h"
#include "WebGLRenderbuffer.h"
#include "WebGLRenderingContext.h"
#include "WebGLShader.h"
#include "WebGLTexture.h"
#include "WebGLUnsignedByteArray.h"
#include <wtf/UnusedParam.h>
#if ENABLE(3D_CANVAS)
namespace WebCore {
#if !defined(GLchar)
typedef char GLchar;
#endif
#if !defined(APIENTRY)
#define APIENTRY
#endif
typedef void (APIENTRY* glActiveTextureType) (GLenum);
typedef void (APIENTRY* glAttachShaderType) (GLuint, GLuint);
typedef void (APIENTRY* glBindAttribLocationType) (GLuint, GLuint, const char*);
typedef void (APIENTRY* glBindBufferType) (GLenum, GLuint);
typedef void (APIENTRY* glBindFramebufferType) (GLenum, GLuint);
typedef void (APIENTRY* glBindRenderbufferType) (GLenum, GLuint);
typedef void (APIENTRY* glBlendColorType) (GLclampf, GLclampf, GLclampf, GLclampf);
typedef void (APIENTRY* glBlendEquationType) (GLenum);
typedef void (APIENTRY* glBlendEquationSeparateType)(GLenum, GLenum);
typedef void (APIENTRY* glBlendFuncSeparateType)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
typedef void (APIENTRY* glBufferDataType) (GLenum, GLsizeiptr, const GLvoid*, GLenum);
typedef void (APIENTRY* glBufferSubDataType) (GLenum, GLintptr, GLsizeiptr, const GLvoid*);
typedef GLenum (APIENTRY* glCheckFramebufferStatusType) (GLenum);
typedef void (APIENTRY* glCompileShaderType) (GLuint);
typedef GLuint (APIENTRY* glCreateProgramType) ();
typedef GLuint (APIENTRY* glCreateShaderType) (GLenum);
typedef void (APIENTRY* glDeleteBuffersType) (GLsizei, const GLuint*);
typedef void (APIENTRY* glDeleteFramebuffersType) (GLsizei n, const GLuint*);
typedef void (APIENTRY* glDeleteProgramType) (GLuint);
typedef void (APIENTRY* glDeleteRenderbuffersType) (GLsizei n, const GLuint*);
typedef void (APIENTRY* glDeleteShaderType) (GLuint);
typedef void (APIENTRY* glDetachShaderType) (GLuint, GLuint);
typedef void (APIENTRY* glDisableVertexAttribArrayType) (GLuint);
typedef void (APIENTRY* glEnableVertexAttribArrayType) (GLuint);
typedef void (APIENTRY* glFramebufferRenderbufferType) (GLenum, GLenum, GLenum, GLuint);
typedef void (APIENTRY* glFramebufferTexture2DType) (GLenum, GLenum, GLenum, GLuint, GLint);
typedef void (APIENTRY* glGenBuffersType) (GLsizei, GLuint*);
typedef void (APIENTRY* glGenerateMipmapType) (GLenum target);
typedef void (APIENTRY* glGenFramebuffersType) (GLsizei, GLuint*);
typedef void (APIENTRY* glGenRenderbuffersType) (GLsizei, GLuint*);
typedef void (APIENTRY* glGetActiveAttribType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
typedef void (APIENTRY* glGetActiveUniformType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
typedef GLint (APIENTRY* glGetAttribLocationType) (GLuint, const char*);
typedef void (APIENTRY* glGetBufferParameterivType) (GLenum, GLenum, GLint*);
typedef void (APIENTRY* glGetFramebufferAttachmentParameterivType) (GLenum, GLenum, GLenum, GLint* params);
typedef void (APIENTRY* glGetProgramInfoLogType) (GLuint, GLsizei, GLsizei*, char*);
typedef void (APIENTRY* glGetProgramivType) (GLuint, GLenum, GLint*);
typedef void (APIENTRY* glGetRenderbufferParameterivType) (GLenum, GLenum, GLint*);
typedef void (APIENTRY* glGetShaderInfoLogType) (GLuint, GLsizei, GLsizei*, char*);
typedef void (APIENTRY* glGetShaderivType) (GLuint, GLenum, GLint*);
typedef void (APIENTRY* glGetShaderSourceType) (GLuint, GLsizei, GLsizei*, char*);
typedef GLint (APIENTRY* glGetUniformLocationType) (GLuint, const char*);
typedef void (APIENTRY* glGetUniformfvType) (GLuint, GLint, GLfloat*);
typedef void (APIENTRY* glGetUniformivType) (GLuint, GLint, GLint*);
typedef void (APIENTRY* glGetVertexAttribfvType) (GLuint, GLenum, GLfloat*);
typedef void (APIENTRY* glGetVertexAttribivType) (GLuint, GLenum, GLint*);
typedef void (APIENTRY* glGetVertexAttribPointervType) (GLuint, GLenum, GLvoid**);
typedef GLboolean (APIENTRY* glIsBufferType) (GLuint);
typedef GLboolean (APIENTRY* glIsFramebufferType) (GLuint);
typedef GLboolean (APIENTRY* glIsProgramType) (GLuint);
typedef GLboolean (APIENTRY* glIsRenderbufferType) (GLuint);
typedef GLboolean (APIENTRY* glIsShaderType) (GLuint);
typedef void (APIENTRY* glLinkProgramType) (GLuint);
typedef void (APIENTRY* glRenderbufferStorageType) (GLenum, GLenum, GLsizei, GLsizei);
typedef void (APIENTRY* glSampleCoverageType) (GLclampf, GLboolean);
typedef void (APIENTRY* glShaderSourceType) (GLuint, GLsizei, const char**, const GLint*);
typedef void (APIENTRY* glStencilFuncSeparateType) (GLenum, GLenum, GLint, GLuint);
typedef void (APIENTRY* glStencilMaskSeparateType) (GLenum, GLuint);
typedef void (APIENTRY* glStencilOpSeparateType) (GLenum, GLenum, GLenum, GLenum);
typedef void (APIENTRY* glUniform1fType) (GLint, GLfloat);
typedef void (APIENTRY* glUniform1fvType) (GLint, GLsizei, const GLfloat*);
typedef void (APIENTRY* glUniform1iType) (GLint, GLint);
typedef void (APIENTRY* glUniform1ivType) (GLint, GLsizei, const GLint*);
typedef void (APIENTRY* glUniform2fType) (GLint, GLfloat, GLfloat);
typedef void (APIENTRY* glUniform2fvType) (GLint, GLsizei, const GLfloat*);
typedef void (APIENTRY* glUniform2iType) (GLint, GLint, GLint);
typedef void (APIENTRY* glUniform2ivType) (GLint, GLsizei, const GLint*);
typedef void (APIENTRY* glUniform3fType) (GLint, GLfloat, GLfloat, GLfloat);
typedef void (APIENTRY* glUniform3fvType) (GLint, GLsizei, const GLfloat*);
typedef void (APIENTRY* glUniform3iType) (GLint, GLint, GLint, GLint);
typedef void (APIENTRY* glUniform3ivType) (GLint, GLsizei, const GLint*);
typedef void (APIENTRY* glUniform4fType) (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
typedef void (APIENTRY* glUniform4fvType) (GLint, GLsizei, const GLfloat*);
typedef void (APIENTRY* glUniform4iType) (GLint, GLint, GLint, GLint, GLint);
typedef void (APIENTRY* glUniform4ivType) (GLint, GLsizei, const GLint*);
typedef void (APIENTRY* glUniformMatrix2fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
typedef void (APIENTRY* glUniformMatrix3fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
typedef void (APIENTRY* glUniformMatrix4fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
typedef void (APIENTRY* glUseProgramType) (GLuint);
typedef void (APIENTRY* glValidateProgramType) (GLuint);
typedef void (APIENTRY* glVertexAttrib1fType) (GLuint, const GLfloat);
typedef void (APIENTRY* glVertexAttrib1fvType) (GLuint, const GLfloat*);
typedef void (APIENTRY* glVertexAttrib2fType) (GLuint, const GLfloat, const GLfloat);
typedef void (APIENTRY* glVertexAttrib2fvType) (GLuint, const GLfloat*);
typedef void (APIENTRY* glVertexAttrib3fType) (GLuint, const GLfloat, const GLfloat, const GLfloat);
typedef void (APIENTRY* glVertexAttrib3fvType) (GLuint, const GLfloat*);
typedef void (APIENTRY* glVertexAttrib4fType) (GLuint, const GLfloat, const GLfloat, const GLfloat, const GLfloat);
typedef void (APIENTRY* glVertexAttrib4fvType) (GLuint, const GLfloat*);
typedef void (APIENTRY* glVertexAttribPointerType) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
class GraphicsContext3DInternal {
public:
GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs);
~GraphicsContext3DInternal();
bool isContextValid() { return m_contextValid; }
glActiveTextureType activeTexture;
glAttachShaderType attachShader;
glBindAttribLocationType bindAttribLocation;
glBindBufferType bindBuffer;
glBindFramebufferType bindFramebuffer;
glBindRenderbufferType bindRenderbuffer;
glBlendColorType blendColor;
glBlendEquationType blendEquation;
glBlendEquationSeparateType blendEquationSeparate;
glBlendFuncSeparateType blendFuncSeparate;
glBufferDataType bufferData;
glBufferSubDataType bufferSubData;
glCheckFramebufferStatusType checkFramebufferStatus;
glCompileShaderType compileShader;
glCreateProgramType createProgram;
glCreateShaderType createShader;
glDeleteBuffersType deleteBuffers;
glDeleteFramebuffersType deleteFramebuffers;
glDeleteProgramType deleteProgram;
glDeleteRenderbuffersType deleteRenderbuffers;
glDeleteShaderType deleteShader;
glDetachShaderType detachShader;
glDisableVertexAttribArrayType disableVertexAttribArray;
glEnableVertexAttribArrayType enableVertexAttribArray;
glFramebufferRenderbufferType framebufferRenderbuffer;
glFramebufferTexture2DType framebufferTexture2D;
glGenBuffersType genBuffers;
glGenerateMipmapType generateMipmap;
glGenFramebuffersType genFramebuffers;
glGenRenderbuffersType genRenderbuffers;
glGetActiveAttribType getActiveAttrib;
glGetActiveUniformType getActiveUniform;
glGetAttribLocationType getAttribLocation;
glGetBufferParameterivType getBufferParameteriv;
glGetFramebufferAttachmentParameterivType getFramebufferAttachmentParameteriv;
glGetProgramInfoLogType getProgramInfoLog;
glGetProgramivType getProgramiv;
glGetRenderbufferParameterivType getRenderbufferParameteriv;
glGetShaderInfoLogType getShaderInfoLog;
glGetShaderivType getShaderiv;
glGetShaderSourceType getShaderSource;
glGetUniformfvType getUniformfv;
glGetUniformivType getUniformiv;
glGetUniformLocationType getUniformLocation;
glGetVertexAttribfvType getVertexAttribfv;
glGetVertexAttribivType getVertexAttribiv;
glGetVertexAttribPointervType getVertexAttribPointerv;
glIsBufferType isBuffer;
glIsFramebufferType isFramebuffer;
glIsProgramType isProgram;
glIsRenderbufferType isRenderbuffer;
glIsShaderType isShader;
glLinkProgramType linkProgram;
glRenderbufferStorageType renderbufferStorage;
glSampleCoverageType sampleCoverage;
glShaderSourceType shaderSource;
glStencilFuncSeparateType stencilFuncSeparate;
glStencilMaskSeparateType stencilMaskSeparate;
glStencilOpSeparateType stencilOpSeparate;
glUniform1fType uniform1f;
glUniform1fvType uniform1fv;
glUniform1iType uniform1i;
glUniform1ivType uniform1iv;
glUniform2fType uniform2f;
glUniform2fvType uniform2fv;
glUniform2iType uniform2i;
glUniform2ivType uniform2iv;
glUniform3fType uniform3f;
glUniform3fvType uniform3fv;
glUniform3iType uniform3i;
glUniform3ivType uniform3iv;
glUniform4fType uniform4f;
glUniform4fvType uniform4fv;
glUniform4iType uniform4i;
glUniform4ivType uniform4iv;
glUniformMatrix2fvType uniformMatrix2fv;
glUniformMatrix3fvType uniformMatrix3fv;
glUniformMatrix4fvType uniformMatrix4fv;
glUseProgramType useProgram;
glValidateProgramType validateProgram;
glVertexAttrib1fType vertexAttrib1f;
glVertexAttrib1fvType vertexAttrib1fv;
glVertexAttrib2fType vertexAttrib2f;
glVertexAttrib2fvType vertexAttrib2fv;
glVertexAttrib3fType vertexAttrib3f;
glVertexAttrib3fvType vertexAttrib3fv;
glVertexAttrib4fType vertexAttrib4f;
glVertexAttrib4fvType vertexAttrib4fv;
glVertexAttribPointerType vertexAttribPointer;
GraphicsContext3D::Attributes m_attrs;
QGLWidget* m_glWidget;
GLuint m_texture;
GLuint m_mainFbo;
GLuint m_currentFbo;
GLuint m_depthBuffer;
QImage m_pixels;
ListHashSet<unsigned long> m_syntheticErrors;
private:
void* getProcAddress(const String& proc);
bool m_contextValid;
};
#if defined (QT_OPENGL_ES_2)
#define GET_PROC_ADDRESS(Proc) Proc
#else
#define GET_PROC_ADDRESS(Proc) reinterpret_cast<Proc##Type>(getProcAddress(#Proc));
#endif
GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs)
: m_attrs(attrs)
, m_glWidget(0)
, m_texture(0)
, m_mainFbo(0)
, m_currentFbo(0)
, m_depthBuffer(0)
, m_contextValid(true)
{
m_attrs.alpha = true;
m_attrs.depth = true;
m_attrs.stencil = false;
m_attrs.antialias = false;
m_attrs.premultipliedAlpha = true;
QGLFormat format;
format.setDepth(true);
format.setSampleBuffers(true);
format.setStencil(false);
m_glWidget = new QGLWidget(format);
if (!m_glWidget->isValid()) {
LOG_ERROR("GraphicsContext3D: QGLWidget does not have a valid context");
m_contextValid = false;
return;
}
m_glWidget->makeCurrent();
activeTexture = GET_PROC_ADDRESS(glActiveTexture);
attachShader = GET_PROC_ADDRESS(glAttachShader);
bindAttribLocation = GET_PROC_ADDRESS(glBindAttribLocation);
bindBuffer = GET_PROC_ADDRESS(glBindBuffer);
bindFramebuffer = GET_PROC_ADDRESS(glBindFramebuffer);
bindRenderbuffer = GET_PROC_ADDRESS(glBindRenderbuffer);
blendColor = GET_PROC_ADDRESS(glBlendColor);
blendEquation = GET_PROC_ADDRESS(glBlendEquation);
blendEquationSeparate = GET_PROC_ADDRESS(glBlendEquationSeparate);
blendFuncSeparate = GET_PROC_ADDRESS(glBlendFuncSeparate);
bufferData = GET_PROC_ADDRESS(glBufferData);
bufferSubData = GET_PROC_ADDRESS(glBufferSubData);
checkFramebufferStatus = GET_PROC_ADDRESS(glCheckFramebufferStatus);
compileShader = GET_PROC_ADDRESS(glCompileShader);
createProgram = GET_PROC_ADDRESS(glCreateProgram);
createShader = GET_PROC_ADDRESS(glCreateShader);
deleteBuffers = GET_PROC_ADDRESS(glDeleteBuffers);
deleteFramebuffers = GET_PROC_ADDRESS(glDeleteFramebuffers);
deleteProgram = GET_PROC_ADDRESS(glDeleteProgram);
deleteRenderbuffers = GET_PROC_ADDRESS(glDeleteRenderbuffers);
deleteShader = GET_PROC_ADDRESS(glDeleteShader);
detachShader = GET_PROC_ADDRESS(glDetachShader);
disableVertexAttribArray = GET_PROC_ADDRESS(glDisableVertexAttribArray);
enableVertexAttribArray = GET_PROC_ADDRESS(glEnableVertexAttribArray);
framebufferRenderbuffer = GET_PROC_ADDRESS(glFramebufferRenderbuffer);
framebufferTexture2D = GET_PROC_ADDRESS(glFramebufferTexture2D);
genBuffers = GET_PROC_ADDRESS(glGenBuffers);
generateMipmap = GET_PROC_ADDRESS(glGenerateMipmap);
genFramebuffers = GET_PROC_ADDRESS(glGenFramebuffers);
genRenderbuffers = GET_PROC_ADDRESS(glGenRenderbuffers);
getActiveAttrib = GET_PROC_ADDRESS(glGetActiveAttrib);
getActiveUniform = GET_PROC_ADDRESS(glGetActiveUniform);
getAttribLocation = GET_PROC_ADDRESS(glGetAttribLocation);
getBufferParameteriv = GET_PROC_ADDRESS(glGetBufferParameteriv);
getFramebufferAttachmentParameteriv = GET_PROC_ADDRESS(glGetFramebufferAttachmentParameteriv);
getProgramInfoLog = GET_PROC_ADDRESS(glGetProgramInfoLog);
getProgramiv = GET_PROC_ADDRESS(glGetProgramiv);
getRenderbufferParameteriv = GET_PROC_ADDRESS(glGetRenderbufferParameteriv);
getShaderInfoLog = GET_PROC_ADDRESS(glGetShaderInfoLog);
getShaderiv = GET_PROC_ADDRESS(glGetShaderiv);
getShaderSource = GET_PROC_ADDRESS(glGetShaderSource);
getUniformfv = GET_PROC_ADDRESS(glGetUniformfv);
getUniformiv = GET_PROC_ADDRESS(glGetUniformiv);
getUniformLocation = GET_PROC_ADDRESS(glGetUniformLocation);
getVertexAttribfv = GET_PROC_ADDRESS(glGetVertexAttribfv);
getVertexAttribiv = GET_PROC_ADDRESS(glGetVertexAttribiv);
getVertexAttribPointerv = GET_PROC_ADDRESS(glGetVertexAttribPointerv);
isBuffer = GET_PROC_ADDRESS(glIsBuffer);
isFramebuffer = GET_PROC_ADDRESS(glIsFramebuffer);
isProgram = GET_PROC_ADDRESS(glIsProgram);
isRenderbuffer = GET_PROC_ADDRESS(glIsRenderbuffer);
isShader = GET_PROC_ADDRESS(glIsShader);
linkProgram = GET_PROC_ADDRESS(glLinkProgram);
renderbufferStorage = GET_PROC_ADDRESS(glRenderbufferStorage);
sampleCoverage = GET_PROC_ADDRESS(glSampleCoverage);
shaderSource = GET_PROC_ADDRESS(glShaderSource);
stencilFuncSeparate = GET_PROC_ADDRESS(glStencilFuncSeparate);
stencilMaskSeparate = GET_PROC_ADDRESS(glStencilMaskSeparate);
stencilOpSeparate = GET_PROC_ADDRESS(glStencilOpSeparate);
uniform1f = GET_PROC_ADDRESS(glUniform1f);
uniform1fv = GET_PROC_ADDRESS(glUniform1fv);
uniform1i = GET_PROC_ADDRESS(glUniform1i);
uniform1iv = GET_PROC_ADDRESS(glUniform1iv);
uniform2f = GET_PROC_ADDRESS(glUniform2f);
uniform2fv = GET_PROC_ADDRESS(glUniform2fv);
uniform2i = GET_PROC_ADDRESS(glUniform2i);
uniform2iv = GET_PROC_ADDRESS(glUniform2iv);
uniform3f = GET_PROC_ADDRESS(glUniform3f);
uniform3fv = GET_PROC_ADDRESS(glUniform3fv);
uniform3i = GET_PROC_ADDRESS(glUniform3i);
uniform3iv = GET_PROC_ADDRESS(glUniform3iv);
uniform4f = GET_PROC_ADDRESS(glUniform4f);
uniform4fv = GET_PROC_ADDRESS(glUniform4fv);
uniform4i = GET_PROC_ADDRESS(glUniform4i);
uniform4iv = GET_PROC_ADDRESS(glUniform4iv);
uniformMatrix2fv = GET_PROC_ADDRESS(glUniformMatrix2fv);
uniformMatrix3fv = GET_PROC_ADDRESS(glUniformMatrix3fv);
uniformMatrix4fv = GET_PROC_ADDRESS(glUniformMatrix4fv);
useProgram = GET_PROC_ADDRESS(glUseProgram);
validateProgram = GET_PROC_ADDRESS(glValidateProgram);
vertexAttrib1f = GET_PROC_ADDRESS(glVertexAttrib1f);
vertexAttrib1fv = GET_PROC_ADDRESS(glVertexAttrib1fv);
vertexAttrib2f = GET_PROC_ADDRESS(glVertexAttrib2f);
vertexAttrib2fv = GET_PROC_ADDRESS(glVertexAttrib2fv);
vertexAttrib3f = GET_PROC_ADDRESS(glVertexAttrib3f);
vertexAttrib3fv = GET_PROC_ADDRESS(glVertexAttrib3fv);
vertexAttrib4f = GET_PROC_ADDRESS(glVertexAttrib4f);
vertexAttrib4fv = GET_PROC_ADDRESS(glVertexAttrib4fv);
vertexAttribPointer = GET_PROC_ADDRESS(glVertexAttribPointer);
if (!m_contextValid) {
LOG_ERROR("GraphicsContext3D: All needed OpenGL extensions are not available");
m_contextValid = false;
return;
}
glGenTextures(1, &m_texture);
glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture);
glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
glTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
genFramebuffers(/* count */ 1, &m_mainFbo);
m_currentFbo = m_mainFbo;
bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_mainFbo);
genRenderbuffers(/* count */ 1, &m_depthBuffer);
bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
#if defined(QT_OPENGL_ES_2)
renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, /* width */ 1, /* height */ 1);
#else
renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, /* width */ 1, /* height */ 1);
#endif
bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_texture, 0);
framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
glClearColor(/* red */ 0, /* green */ 0, /* blue */ 0, /* alpha */ 0);
if (checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
LOG_ERROR("GraphicsContext3D: Wasn't able to create the main framebuffer");
m_contextValid = false;
}
}
GraphicsContext3DInternal::~GraphicsContext3DInternal()
{
delete m_glWidget;
m_glWidget = 0;
}
void* GraphicsContext3DInternal::getProcAddress(const String& proc)
{
String ext[3] = { "", "ARB", "EXT" };
for (int i = 0; i < 3; i++) {
String nameWithExt = proc + ext[i];
void* addr = m_glWidget->context()->getProcAddress(nameWithExt.utf8().data());
if (addr)
return addr;
}
LOG_ERROR("GraphicsContext3D: Did not find GL function %s", proc.utf8().data());
m_contextValid = false;
return 0;
}
PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs)
{
OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs));
return context->m_internal ? context.release() : 0;
}
GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs)
: m_internal(new GraphicsContext3DInternal(attrs))
{
if (!m_internal->isContextValid())
m_internal = 0;
}
GraphicsContext3D::~GraphicsContext3D()
{
}
PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
{
return m_internal->m_glWidget;
}
Platform3DObject GraphicsContext3D::platformTexture() const
{
return m_internal->m_texture;
}
void GraphicsContext3D::makeContextCurrent()
{
m_internal->m_glWidget->makeCurrent();
}
void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
{
m_internal->m_glWidget->makeCurrent();
HTMLCanvasElement* canvas = context->canvas();
ImageBuffer* imageBuffer = canvas->buffer();
m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo);
glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits());
QPainter* p = imageBuffer->context()->platformContext();
p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.transformed(QMatrix().rotate(180)));
m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo);
}
void GraphicsContext3D::endPaint()
{
}
void GraphicsContext3D::reshape(int width, int height)
{
if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal))
return;
m_currentWidth = width;
m_currentHeight = height;
m_internal->m_pixels = QImage(m_currentWidth, m_currentHeight, QImage::Format_ARGB32);
m_internal->m_glWidget->makeCurrent();
glBindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->m_texture);
glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0);
glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo);
m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer);
#if defined(QT_OPENGL_ES_2)
renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height);
#else
renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height);
#endif
m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
m_internal->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_internal->m_texture, 0);
m_internal->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer);
GLenum status = m_internal->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER);
if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
LOG_ERROR("GraphicsContext3D: Wasn't able to reshape the main framebuffer");
notImplemented();
}
glClear(GraphicsContext3D::COLOR_BUFFER_BIT);
glFlush();
}
void GraphicsContext3D::activeTexture(unsigned long texture)
{
m_internal->m_glWidget->makeCurrent();
m_internal->activeTexture(texture);
}
void GraphicsContext3D::attachShader(WebGLProgram* program, WebGLShader* shader)
{
ASSERT(program);
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
m_internal->attachShader((GLuint) program->object(), (GLuint) shader->object());
}
void GraphicsContext3D::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
m_internal->bindAttribLocation((GLuint) program->object(), index, name.utf8().data());
}
void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->bindBuffer(target, buffer ? (GLuint) buffer->object() : 0);
}
void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->m_currentFbo = (buffer && buffer->object()) ? (GLuint) buffer->object() : m_internal->m_mainFbo;
m_internal->bindFramebuffer(target, m_internal->m_currentFbo);
}
void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->bindRenderbuffer(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
}
void GraphicsContext3D::bindTexture(unsigned long target, WebGLTexture* texture)
{
m_internal->m_glWidget->makeCurrent();
glBindTexture(target, texture ? (GLuint) texture->object() : 0);
}
void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha)
{
m_internal->m_glWidget->makeCurrent();
m_internal->blendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
}
void GraphicsContext3D::blendEquation(unsigned long mode)
{
m_internal->m_glWidget->makeCurrent();
m_internal->blendEquation(mode);
}
void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
{
m_internal->m_glWidget->makeCurrent();
m_internal->blendEquationSeparate(modeRGB, modeAlpha);
}
void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor)
{
m_internal->m_glWidget->makeCurrent();
glBlendFunc(sfactor, dfactor);
}
void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
{
m_internal->m_glWidget->makeCurrent();
m_internal->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage)
{
m_internal->m_glWidget->makeCurrent();
m_internal->bufferData(target, size, /* data */ 0, usage);
}
void GraphicsContext3D::bufferData(unsigned long target, WebGLArray* array, unsigned long usage)
{
if (!array || !array->length())
return;
m_internal->m_glWidget->makeCurrent();
m_internal->bufferData(target, array->byteLength(), array->baseAddress(), usage);
}
void GraphicsContext3D::bufferSubData(unsigned long target, long offset, WebGLArray* array)
{
if (!array || !array->length())
return;
m_internal->m_glWidget->makeCurrent();
m_internal->bufferSubData(target, offset, array->byteLength(), array->baseAddress());
}
unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
{
m_internal->m_glWidget->makeCurrent();
return m_internal->checkFramebufferStatus(target);
}
void GraphicsContext3D::clearColor(double r, double g, double b, double a)
{
m_internal->m_glWidget->makeCurrent();
glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a));
}
void GraphicsContext3D::clear(unsigned long mask)
{
m_internal->m_glWidget->makeCurrent();
glClear(mask);
}
void GraphicsContext3D::clearDepth(double depth)
{
m_internal->m_glWidget->makeCurrent();
#if defined(QT_OPENGL_ES_2)
glClearDepthf(depth);
#else
glClearDepth(depth);
#endif
}
void GraphicsContext3D::clearStencil(long s)
{
m_internal->m_glWidget->makeCurrent();
glClearStencil(s);
}
void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
{
m_internal->m_glWidget->makeCurrent();
glColorMask(red, green, blue, alpha);
}
void GraphicsContext3D::compileShader(WebGLShader* shader)
{
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
m_internal->compileShader((GLuint) shader->object());
}
void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border)
{
m_internal->m_glWidget->makeCurrent();
glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
}
void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height)
{
m_internal->m_glWidget->makeCurrent();
glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
}
void GraphicsContext3D::cullFace(unsigned long mode)
{
m_internal->m_glWidget->makeCurrent();
glCullFace(mode);
}
void GraphicsContext3D::depthFunc(unsigned long func)
{
m_internal->m_glWidget->makeCurrent();
glDepthFunc(func);
}
void GraphicsContext3D::depthMask(bool flag)
{
m_internal->m_glWidget->makeCurrent();
glDepthMask(flag);
}
void GraphicsContext3D::depthRange(double zNear, double zFar)
{
m_internal->m_glWidget->makeCurrent();
#if defined(QT_OPENGL_ES_2)
glDepthRangef(zNear, zFar);
#else
glDepthRange(zNear, zFar);
#endif
}
void GraphicsContext3D::detachShader(WebGLProgram* program, WebGLShader* shader)
{
ASSERT(program);
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
m_internal->detachShader((GLuint) program->object(), (GLuint) shader->object());
}
void GraphicsContext3D::disable(unsigned long cap)
{
m_internal->m_glWidget->makeCurrent();
glDisable(cap);
}
void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
{
m_internal->m_glWidget->makeCurrent();
m_internal->disableVertexAttribArray(index);
}
void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
{
m_internal->m_glWidget->makeCurrent();
glDrawArrays(mode, first, count);
}
void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset)
{
m_internal->m_glWidget->makeCurrent();
glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
}
void GraphicsContext3D::enable(unsigned long cap)
{
m_internal->m_glWidget->makeCurrent();
glEnable(cap);
}
void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
{
m_internal->m_glWidget->makeCurrent();
m_internal->enableVertexAttribArray(index);
}
void GraphicsContext3D::finish()
{
m_internal->m_glWidget->makeCurrent();
glFinish();
}
void GraphicsContext3D::flush()
{
m_internal->m_glWidget->makeCurrent();
glFlush();
}
void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->framebufferRenderbuffer(target, attachment, renderbuffertarget, buffer ? (GLuint) buffer->object() : 0);
}
void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level)
{
m_internal->m_glWidget->makeCurrent();
m_internal->framebufferTexture2D(target, attachment, textarget, texture ? (GLuint) texture->object() : 0, level);
}
void GraphicsContext3D::frontFace(unsigned long mode)
{
m_internal->m_glWidget->makeCurrent();
glFrontFace(mode);
}
void GraphicsContext3D::generateMipmap(unsigned long target)
{
m_internal->m_glWidget->makeCurrent();
m_internal->generateMipmap(target);
}
bool GraphicsContext3D::getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo& info)
{
if (!program->object()) {
synthesizeGLError(INVALID_VALUE);
return false;
}
m_internal->m_glWidget->makeCurrent();
GLint maxLength;
m_internal->getProgramiv(static_cast<GLuint>(program->object()), GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
GLchar name[maxLength];
GLsizei nameLength;
GLint size;
GLenum type;
m_internal->getActiveAttrib(static_cast<GLuint>(program->object()), index, maxLength, &nameLength, &size, &type, name);
if (!nameLength)
return false;
info.name = String(name, nameLength);
info.type = type;
info.size = size;
return true;
}
bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo& info)
{
if (!program->object()) {
synthesizeGLError(INVALID_VALUE);
return false;
}
m_internal->m_glWidget->makeCurrent();
GLint maxLength;
m_internal->getProgramiv(static_cast<GLuint>(program->object()), GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
GLchar name[maxLength];
GLsizei nameLength;
GLint size;
GLenum type;
m_internal->getActiveUniform(static_cast<GLuint>(program->object()), index, maxLength, &nameLength, &size, &type, name);
if (!nameLength)
return false;
info.name = String(name, nameLength);
info.type = type;
info.size = size;
return true;
}
int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name)
{
if (!program)
return -1;
m_internal->m_glWidget->makeCurrent();
return m_internal->getAttribLocation((GLuint) program->object(), name.utf8().data());
}
GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
{
return m_internal->m_attrs;
}
unsigned long GraphicsContext3D::getError()
{
if (m_internal->m_syntheticErrors.size() > 0) {
ListHashSet<unsigned long>::iterator iter = m_internal->m_syntheticErrors.begin();
unsigned long err = *iter;
m_internal->m_syntheticErrors.remove(iter);
return err;
}
m_internal->m_glWidget->makeCurrent();
return glGetError();
}
String GraphicsContext3D::getString(unsigned long name)
{
m_internal->m_glWidget->makeCurrent();
return String((const char*) glGetString(name));
}
void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
{
m_internal->m_glWidget->makeCurrent();
glHint(target, mode);
}
bool GraphicsContext3D::isBuffer(WebGLBuffer* buffer)
{
if (!buffer)
return false;
m_internal->m_glWidget->makeCurrent();
return m_internal->isBuffer((GLuint) buffer->object());
}
bool GraphicsContext3D::isEnabled(unsigned long cap)
{
m_internal->m_glWidget->makeCurrent();
return glIsEnabled(cap);
}
bool GraphicsContext3D::isFramebuffer(WebGLFramebuffer* framebuffer)
{
if (!framebuffer)
return false;
m_internal->m_glWidget->makeCurrent();
return m_internal->isFramebuffer((GLuint) framebuffer->object());
}
bool GraphicsContext3D::isProgram(WebGLProgram* program)
{
if (!program)
return false;
m_internal->m_glWidget->makeCurrent();
return m_internal->isProgram((GLuint) program->object());
}
bool GraphicsContext3D::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
{
if (!renderbuffer)
return false;
m_internal->m_glWidget->makeCurrent();
return m_internal->isRenderbuffer((GLuint) renderbuffer->object());
}
bool GraphicsContext3D::isShader(WebGLShader* shader)
{
if (!shader)
return false;
m_internal->m_glWidget->makeCurrent();
return m_internal->isShader((GLuint) shader->object());
}
bool GraphicsContext3D::isTexture(WebGLTexture* texture)
{
if (!texture)
return false;
m_internal->m_glWidget->makeCurrent();
return glIsTexture((GLuint) texture->object());
}
void GraphicsContext3D::lineWidth(double width)
{
m_internal->m_glWidget->makeCurrent();
glLineWidth(static_cast<float>(width));
}
void GraphicsContext3D::linkProgram(WebGLProgram* program)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
m_internal->linkProgram((GLuint) program->object());
}
void GraphicsContext3D::pixelStorei(unsigned long paramName, long param)
{
m_internal->m_glWidget->makeCurrent();
glPixelStorei(paramName, param);
}
void GraphicsContext3D::polygonOffset(double factor, double units)
{
m_internal->m_glWidget->makeCurrent();
glPolygonOffset(static_cast<float>(factor), static_cast<float>(units));
}
PassRefPtr<WebGLArray> GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
{
m_internal->m_glWidget->makeCurrent();
if (type != GraphicsContext3D::UNSIGNED_BYTE || format != GraphicsContext3D::RGBA)
return 0;
RefPtr<WebGLUnsignedByteArray> array = WebGLUnsignedByteArray::create(width * height * 4);
glReadPixels(x, y, width, height, format, type, (GLvoid*) array->data());
return array;
}
void GraphicsContext3D::releaseShaderCompiler()
{
m_internal->m_glWidget->makeCurrent();
notImplemented();
}
void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
{
m_internal->m_glWidget->makeCurrent();
m_internal->renderbufferStorage(target, internalformat, width, height);
}
void GraphicsContext3D::sampleCoverage(double value, bool invert)
{
m_internal->m_glWidget->makeCurrent();
m_internal->sampleCoverage(static_cast<float>(value), invert);
}
void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height)
{
m_internal->m_glWidget->makeCurrent();
glScissor(x, y, width, height);
}
void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& source)
{
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
CString sourceCS = source.utf8();
const char* data = sourceCS.data();
int length = source.length();
m_internal->shaderSource((GLuint) shader->object(), /* count */ 1, &data, &length);
}
void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask)
{
m_internal->m_glWidget->makeCurrent();
glStencilFunc(func, ref, mask);
}
void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
{
m_internal->m_glWidget->makeCurrent();
m_internal->stencilFuncSeparate(face, func, ref, mask);
}
void GraphicsContext3D::stencilMask(unsigned long mask)
{
m_internal->m_glWidget->makeCurrent();
glStencilMask(mask);
}
void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask)
{
m_internal->m_glWidget->makeCurrent();
m_internal->stencilMaskSeparate(face, mask);
}
void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
{
m_internal->m_glWidget->makeCurrent();
glStencilOp(fail, zfail, zpass);
}
void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
{
m_internal->m_glWidget->makeCurrent();
m_internal->stencilOpSeparate(face, fail, zfail, zpass);
}
void GraphicsContext3D::texParameterf(unsigned target, unsigned paramName, float value)
{
m_internal->m_glWidget->makeCurrent();
glTexParameterf(target, paramName, static_cast<float>(value));
}
void GraphicsContext3D::texParameteri(unsigned target, unsigned paramName, int value)
{
m_internal->m_glWidget->makeCurrent();
glTexParameteri(target, paramName, static_cast<float>(value));
}
void GraphicsContext3D::uniform1f(long location, float v0)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform1f(location, v0);
}
void GraphicsContext3D::uniform1fv(long location, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform1fv(location, size, array);
}
void GraphicsContext3D::uniform2f(long location, float v0, float v1)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform2f(location, v0, v1);
}
void GraphicsContext3D::uniform2fv(long location, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform2fv(location, size, array);
}
void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform3f(location, v0, v1, v2);
}
void GraphicsContext3D::uniform3fv(long location, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform3fv(location, size, array);
}
void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform4f(location, v0, v1, v2, v3);
}
void GraphicsContext3D::uniform4fv(long location, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform4fv(location, size, array);
}
void GraphicsContext3D::uniform1i(long location, int v0)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform1i(location, v0);
}
void GraphicsContext3D::uniform1iv(long location, int* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform1iv(location, size, array);
}
void GraphicsContext3D::uniform2i(long location, int v0, int v1)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform2i(location, v0, v1);
}
void GraphicsContext3D::uniform2iv(long location, int* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform2iv(location, size, array);
}
void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform3i(location, v0, v1, v2);
}
void GraphicsContext3D::uniform3iv(long location, int* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform3iv(location, size, array);
}
void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform4i(location, v0, v1, v2, v3);
}
void GraphicsContext3D::uniform4iv(long location, int* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniform4iv(location, size, array);
}
void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniformMatrix2fv(location, size, transpose, array);
}
void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniformMatrix3fv(location, size, transpose, array);
}
void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size)
{
m_internal->m_glWidget->makeCurrent();
m_internal->uniformMatrix4fv(location, size, transpose, array);
}
void GraphicsContext3D::useProgram(WebGLProgram* program)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
m_internal->useProgram((GLuint) program->object());
}
void GraphicsContext3D::validateProgram(WebGLProgram* program)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
m_internal->validateProgram((GLuint) program->object());
}
void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib1f(indx, v0);
}
void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib1fv(indx, array);
}
void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib2f(indx, v0, v1);
}
void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib2fv(indx, array);
}
void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib3f(indx, v0, v1, v2);
}
void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib3fv(indx, array);
}
void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib4f(indx, v0, v1, v2, v3);
}
void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttrib4fv(indx, array);
}
void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset)
{
m_internal->m_glWidget->makeCurrent();
m_internal->vertexAttribPointer(indx, size, type, normalized, stride, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
}
void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height)
{
m_internal->m_glWidget->makeCurrent();
glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
}
void GraphicsContext3D::getBooleanv(unsigned long paramName, unsigned char* value)
{
m_internal->m_glWidget->makeCurrent();
glGetBooleanv(paramName, value);
}
void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getBufferParameteriv(target, paramName, value);
}
void GraphicsContext3D::getFloatv(unsigned long paramName, float* value)
{
m_internal->m_glWidget->makeCurrent();
glGetFloatv(paramName, value);
}
void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getFramebufferAttachmentParameteriv(target, attachment, paramName, value);
}
void GraphicsContext3D::getIntegerv(unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
glGetIntegerv(paramName, value);
}
void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getProgramiv((GLuint) program->object(), paramName, value);
}
String GraphicsContext3D::getProgramInfoLog(WebGLProgram* program)
{
m_internal->m_glWidget->makeCurrent();
GLint length;
m_internal->getProgramiv((GLuint) program->object(), GraphicsContext3D::INFO_LOG_LENGTH, &length);
GLsizei size;
GLchar* info = (GLchar*) fastMalloc(length);
if (!info)
return "";
m_internal->getProgramInfoLog((GLuint) program->object(), length, &size, info);
String result(info);
fastFree(info);
return result;
}
void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getRenderbufferParameteriv(target, paramName, value);
}
void GraphicsContext3D::getShaderiv(WebGLShader* shader, unsigned long paramName, int* value)
{
ASSERT(shader);
m_internal->m_glWidget->makeCurrent();
m_internal->getShaderiv((GLuint) shader->object(), paramName, value);
}
String GraphicsContext3D::getShaderInfoLog(WebGLShader* shader)
{
m_internal->m_glWidget->makeCurrent();
GLint length;
m_internal->getShaderiv((GLuint) shader->object(), GraphicsContext3D::INFO_LOG_LENGTH, &length);
GLsizei size;
GLchar* info = (GLchar*) fastMalloc(length);
if (!info)
return "";
m_internal->getShaderInfoLog((GLuint) shader->object(), length, &size, info);
String result(info);
fastFree(info);
return result;
}
String GraphicsContext3D::getShaderSource(WebGLShader* shader)
{
m_internal->m_glWidget->makeCurrent();
GLint length;
m_internal->getShaderiv((GLuint) shader->object(), GraphicsContext3D::SHADER_SOURCE_LENGTH, &length);
GLsizei size;
GLchar* info = (GLchar*) fastMalloc(length);
if (!info)
return "";
m_internal->getShaderSource((GLuint) shader->object(), length, &size, info);
String result(info);
fastFree(info);
return result;
}
void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long paramName, float* value)
{
m_internal->m_glWidget->makeCurrent();
glGetTexParameterfv(target, paramName, value);
}
void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
glGetTexParameteriv(target, paramName, value);
}
void GraphicsContext3D::getUniformfv(WebGLProgram* program, long location, float* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getUniformfv((GLuint) program->object(), location, value);
}
void GraphicsContext3D::getUniformiv(WebGLProgram* program, long location, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getUniformiv((GLuint) program->object(), location, value);
}
long GraphicsContext3D::getUniformLocation(WebGLProgram* program, const String& name)
{
ASSERT(program);
m_internal->m_glWidget->makeCurrent();
return m_internal->getUniformLocation((GLuint) program->object(), name.utf8().data());
}
void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long paramName, float* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getVertexAttribfv(index, paramName, value);
}
void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long paramName, int* value)
{
m_internal->m_glWidget->makeCurrent();
m_internal->getVertexAttribiv(index, paramName, value);
}
long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long paramName)
{
m_internal->m_glWidget->makeCurrent();
void* pointer;
m_internal->getVertexAttribPointerv(index, paramName, &pointer);
return reinterpret_cast<long>(pointer);
}
int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels)
{
glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
return 0;
}
int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha)
{
ASSERT(image);
m_internal->m_glWidget->makeCurrent();
Vector<uint8_t> imageData;
GLuint format;
GLuint internalFormat;
if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) {
LOG_ERROR("GraphicsContext3D::texImage2D: could not extract Image data");
return -1;
}
glTexImage2D(target, level, internalFormat, image->width(), image->height(),
/* border */ 0, format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data());
return 0;
}
int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels)
{
glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
return 0;
}
int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha)
{
ASSERT(image);
Vector<uint8_t> imageData;
GLuint format;
GLuint internalFormat;
if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) {
LOG_ERROR("GraphicsContext3D::texSubImage2D: could not extract Image data");
return -1;
}
glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(),
format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data());
return 0;
}
unsigned GraphicsContext3D::createBuffer()
{
m_internal->m_glWidget->makeCurrent();
GLuint handle;
m_internal->genBuffers(/* count */ 1, &handle);
return handle;
}
unsigned GraphicsContext3D::createFramebuffer()
{
m_internal->m_glWidget->makeCurrent();
GLuint handle;
m_internal->genFramebuffers(/* count */ 1, &handle);
return handle;
}
unsigned GraphicsContext3D::createProgram()
{
m_internal->m_glWidget->makeCurrent();
return m_internal->createProgram();
}
unsigned GraphicsContext3D::createRenderbuffer()
{
m_internal->m_glWidget->makeCurrent();
GLuint handle;
m_internal->genRenderbuffers(/* count */ 1, &handle);
return handle;
}
unsigned GraphicsContext3D::createShader(unsigned long type)
{
m_internal->m_glWidget->makeCurrent();
return m_internal->createShader((type == FRAGMENT_SHADER) ? GraphicsContext3D::FRAGMENT_SHADER : GraphicsContext3D::VERTEX_SHADER);
}
unsigned GraphicsContext3D::createTexture()
{
m_internal->m_glWidget->makeCurrent();
GLuint handle;
glGenTextures(1, &handle);
return handle;
}
void GraphicsContext3D::deleteBuffer(unsigned buffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->deleteBuffers(1, &buffer);
}
void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->deleteFramebuffers(1, &framebuffer);
}
void GraphicsContext3D::deleteProgram(unsigned program)
{
m_internal->m_glWidget->makeCurrent();
m_internal->deleteProgram(program);
}
void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
{
m_internal->m_glWidget->makeCurrent();
m_internal->deleteRenderbuffers(1, &renderbuffer);
}
void GraphicsContext3D::deleteShader(unsigned shader)
{
m_internal->m_glWidget->makeCurrent();
m_internal->deleteShader(shader);
}
void GraphicsContext3D::deleteTexture(unsigned texture)
{
m_internal->m_glWidget->makeCurrent();
glDeleteTextures(1, &texture);
}
int GraphicsContext3D::sizeInBytes(int type)
{
switch (type) {
case GraphicsContext3D::BYTE:
return sizeof(GLbyte);
case GraphicsContext3D::UNSIGNED_BYTE:
return sizeof(GLubyte);
case GraphicsContext3D::SHORT:
return sizeof(GLshort);
case GraphicsContext3D::UNSIGNED_SHORT:
return sizeof(GLushort);
case GraphicsContext3D::INT:
return sizeof(GLint);
case GraphicsContext3D::UNSIGNED_INT:
return sizeof(GLuint);
case GraphicsContext3D::FLOAT:
return sizeof(GLfloat);
default:
return 0;
}
}
void GraphicsContext3D::synthesizeGLError(unsigned long error)
{
m_internal->m_syntheticErrors.add(error);
}
bool GraphicsContext3D::getImageData(Image* image,
Vector<uint8_t>& outputVector,
bool premultiplyAlpha,
bool* hasAlphaChannel,
AlphaOp* neededAlphaOp,
unsigned int* format)
{
QImage::Format imageFormat = (!premultiplyAlpha) ?
QImage::Format_ARGB32 :
QImage::Format_ARGB32_Premultiplied;
QPixmap* nativePixmap = image->nativeImageForCurrentFrame();
*hasAlphaChannel = true;
*neededAlphaOp = kAlphaDoNothing;
*format = GraphicsContext3D::RGBA;
QImage nativeImage = nativePixmap->toImage().convertToFormat(imageFormat);
outputVector.append(nativeImage.bits(), nativeImage.byteCount());
return true;
}
}
#endif // ENABLE(3D_CANVAS)