Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Unified Diff: webkit/api/src/GraphicsContext3D.cpp

Issue 256037: Ported Chrome's WebGL implementation to Mac OS X. Removed code which... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/glew/src/glew.c ('k') | webkit/webkit.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/api/src/GraphicsContext3D.cpp
===================================================================
--- webkit/api/src/GraphicsContext3D.cpp (revision 27788)
+++ webkit/api/src/GraphicsContext3D.cpp (working copy)
@@ -63,8 +63,24 @@
#include "GL/glew.h"
+#if PLATFORM(CG)
+#include "GraphicsContext.h"
+#include <CoreGraphics/CGContext.h>
+#include <CoreGraphics/CGBitmapContext.h>
+#include <CoreGraphics/CGImage.h>
+#include <OpenGL/OpenGL.h>
+#else
+#define FLIP_FRAMEBUFFER_VERTICALLY
+#endif
+
+#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
+#endif
+#if PLATFORM(DARWIN)
+#define USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER
+#endif
+
using namespace std;
namespace WebCore {
@@ -100,13 +116,8 @@
void bindTexture(unsigned long target,
CanvasTexture* texture);
void bufferDataImpl(unsigned long target, int size, const void* data, unsigned long usage);
- void colorMask(bool red, bool green, bool blue, bool alpha);
- void depthMask(bool flag);
- void disable(unsigned long cap);
void disableVertexAttribArray(unsigned long index);
- void enable(unsigned long cap);
void enableVertexAttribArray(unsigned long index);
- void useProgram(CanvasProgram* program);
void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
unsigned long stride, unsigned long offset);
void viewportImpl(long x, long y, unsigned long width, unsigned long height);
@@ -115,20 +126,18 @@
unsigned int m_texture;
unsigned int m_fbo;
unsigned int m_depthBuffer;
+ unsigned int m_cachedWidth, m_cachedHeight;
- // Objects for flipping the render output vertically
- unsigned int m_altTexture;
- unsigned int m_quadVBO;
- unsigned int m_quadProgram;
- unsigned int m_quadTexLocation;
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ unsigned char* m_scanline;
+ void flipVertically(unsigned char* framebuffer,
+ unsigned int width,
+ unsigned int height);
+#endif
- // Storage for saving/restoring buffer, vertex attribute,
- // blending, and program state when drawing flipped quad
- unsigned int m_currentProgram;
- bool m_blendEnabled;
- bool m_depthTestEnabled;
- bool m_depthMaskEnabled;
- bool m_colorMask[4];
+ // Note: we aren't currently using this information, but we will
+ // need to in order to verify that all enabled vertex arrays have
+ // a valid buffer bound -- to avoid crashes on certain cards.
unsigned int m_boundArrayBuffer;
class VertexAttribPointerState {
public:
@@ -143,22 +152,21 @@
unsigned long stride;
unsigned long offset;
};
- VertexAttribPointerState m_vertexAttribPointerState[1];
- unsigned int m_activeTextureUnit;
- class TextureUnitState {
- public:
- TextureUnitState();
- unsigned long target;
- unsigned int texture;
+ enum {
+ NumTrackedPointerStates = 2
};
- TextureUnitState m_textureUnitState[1];
- int m_viewport[4];
+ VertexAttribPointerState m_vertexAttribPointerState[NumTrackedPointerStates];
#if PLATFORM(WIN_OS)
HWND m_canvasWindow;
HDC m_canvasDC;
HGLRC m_contextObj;
+#elif PLATFORM(CG)
+ CGLPBufferObj m_pbuffer;
+ CGLContextObj m_contextObj;
+ unsigned char* m_renderOutput;
+ CGContextRef m_cgContext;
#else
#error Must port GraphicsContext3D to your platform
#endif
@@ -176,38 +184,27 @@
{
}
-GraphicsContext3DInternal::TextureUnitState::TextureUnitState()
- : target(0)
- , texture(0)
-{
-}
-
GraphicsContext3DInternal::GraphicsContext3DInternal()
: m_texture(0)
, m_fbo(0)
, m_depthBuffer(0)
- , m_altTexture(0)
- , m_quadVBO(0)
- , m_quadProgram(0)
- , m_quadTexLocation(0)
- , m_currentProgram(0)
- , m_blendEnabled(false)
- , m_depthTestEnabled(false)
- , m_depthMaskEnabled(true)
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ , m_scanline(NULL)
+#endif
, m_boundArrayBuffer(0)
- , m_activeTextureUnit(0)
#if PLATFORM(WIN_OS)
, m_canvasWindow(NULL)
, m_canvasDC(NULL)
, m_contextObj(NULL)
+#elif PLATFORM(CG)
+ , m_pbuffer(NULL)
+ , m_contextObj(NULL)
+ , m_renderOutput(NULL)
+ , m_cgContext(NULL)
#else
#error Must port to your platform
#endif
{
- for (int i = 0; i < 4; i++) {
- m_viewport[i] = 0;
- m_colorMask[i] = true;
- }
#if PLATFORM(WIN_OS)
WNDCLASS wc;
if (!GetClassInfo(GetModuleHandle(NULL), L"CANVASGL", &wc)) {
@@ -277,12 +274,59 @@
setSwapInterval(1);
#endif // RENDER_TO_DEBUGGING_WINDOW
+#elif PLATFORM(CG)
+ // Create a 1x1 pbuffer and associated context to bootstrap things
+ CGLPixelFormatAttribute attribs[] = {
+ (CGLPixelFormatAttribute) kCGLPFAPBuffer,
+ (CGLPixelFormatAttribute) 0
+ };
+ CGLPixelFormatObj pixelFormat;
+ GLint numPixelFormats;
+ if (CGLChoosePixelFormat(attribs, &pixelFormat, &numPixelFormats) != kCGLNoError) {
+ printf("GraphicsContext3D: error choosing pixel format\n");
+ return;
+ }
+ if (pixelFormat == NULL) {
+ printf("GraphicsContext3D: no pixel format selected\n");
+ return;
+ }
+ CGLContextObj context;
+ CGLError res = CGLCreateContext(pixelFormat, NULL, &context);
+ CGLDestroyPixelFormat(pixelFormat);
+ if (res != kCGLNoError) {
+ printf("GraphicsContext3D: error creating context\n");
+ return;
+ }
+ CGLPBufferObj pbuffer;
+ if (CGLCreatePBuffer(1, 1, GL_TEXTURE_2D, GL_RGBA, 0, &pbuffer) != kCGLNoError) {
+ CGLDestroyContext(context);
+ printf("GraphicsContext3D: error creating pbuffer\n");
+ return;
+ }
+ if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) {
+ CGLDestroyContext(context);
+ CGLDestroyPBuffer(pbuffer);
+ printf("GraphicsContext3D: error attaching pbuffer to context\n");
+ return;
+ }
+ if (CGLSetCurrentContext(context) != kCGLNoError) {
+ CGLDestroyContext(context);
+ CGLDestroyPBuffer(pbuffer);
+ printf("GraphicsContext3D: error making context current\n");
+ return;
+ }
+ m_pbuffer = pbuffer;
+ m_contextObj = context;
#else
#error Must port to your platform
#endif
// Initialize GLEW and check for GL 2.0 support by the drivers.
GLenum glewInitResult = glewInit();
+ if (glewInitResult != GLEW_OK) {
+ printf("GraphicsContext3D: GLEW initialization failed\n");
+ return;
+ }
if (!glewIsSupported("GL_VERSION_2_0")) {
printf("GraphicsContext3D: OpenGL 2.0 not supported\n");
return;
@@ -295,7 +339,10 @@
#ifndef RENDER_TO_DEBUGGING_WINDOW
glDeleteRenderbuffersEXT(1, &m_depthBuffer);
glDeleteTextures(1, &m_texture);
- glDeleteTextures(1, &m_altTexture);
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (m_scanline != NULL)
+ delete[] m_scanline;
+#endif
glDeleteFramebuffersEXT(1, &m_fbo);
#endif // !RENDER_TO_DEBUGGING_WINDOW
#if PLATFORM(WIN_OS)
@@ -303,6 +350,14 @@
wglDeleteContext(m_contextObj);
ReleaseDC(m_canvasWindow, m_canvasDC);
DestroyWindow(m_canvasWindow);
+#elif PLATFORM(CG)
+ CGLSetCurrentContext(NULL);
+ CGLDestroyContext(m_contextObj);
+ CGLDestroyPBuffer(m_pbuffer);
+ if (m_cgContext != NULL)
+ CGContextRelease(m_cgContext);
+ if (m_renderOutput != NULL)
+ delete[] m_renderOutput;
#else
#error Must port to your platform
#endif
@@ -315,7 +370,7 @@
// will need to throw an exception on error.
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
- printf("GL Error : %x\n", error);
+ printf("GraphicsContext3DInternal: GL Error : %x\n", error);
notImplemented();
}
}
@@ -326,6 +381,10 @@
if (wglGetCurrentContext() != m_contextObj)
if (wglMakeCurrent(m_canvasDC, m_contextObj))
return true;
+#elif PLATFORM(CG)
+ if (CGLGetCurrentContext() != m_contextObj)
+ if (CGLSetCurrentContext(m_contextObj) == kCGLNoError)
+ return true;
#else
#error Must port to your platform
#endif
@@ -342,13 +401,13 @@
return m_texture;
}
-static int createTextureObject()
+static int createTextureObject(GLenum target)
{
GLuint texture = 0;
glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindTexture(target, texture);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return texture;
}
@@ -360,36 +419,38 @@
ShowWindow(m_canvasWindow, SW_SHOW);
#endif
+ m_cachedWidth = width;
+ m_cachedHeight = height;
makeContextCurrent();
#ifndef RENDER_TO_DEBUGGING_WINDOW
+#ifdef USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER
+ // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on Mac OS X
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+#else
+ GLenum target = GL_TEXTURE_2D;
+#endif
if (m_texture == 0) {
- // Generate the texture objects
- m_texture = createTextureObject();
- m_altTexture = createTextureObject();
-
+ // Generate the texture object
+ m_texture = createTextureObject(target);
// Generate the framebuffer object
glGenFramebuffersEXT(1, &m_fbo);
-
// Generate the depth buffer
glGenRenderbuffersEXT(1, &m_depthBuffer);
-
checkError();
}
// Reallocate the color and depth buffers
- glBindTexture(GL_TEXTURE_2D, m_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glBindTexture(GL_TEXTURE_2D, m_altTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(target, m_texture);
+ glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glBindTexture(target, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, m_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
@@ -398,12 +459,63 @@
// FIXME: cleanup.
notImplemented();
}
-#endif // RENDER_TO_DEBUGGING_WINDOW
+#endif // RENDER_TO_DEBUGGING_WINDOW
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (m_scanline != NULL) {
+ delete[] m_scanline;
+ m_scanline = NULL;
+ }
+ m_scanline = new unsigned char[width * 4];
+#endif // FLIP_FRAMEBUFFER_VERTICALLY
+
glClear(GL_COLOR_BUFFER_BIT);
viewportImpl(0, 0, width, height);
+
+#if PLATFORM(CG)
+ // Need to reallocate the client-side backing store.
+ // FIXME: make this more efficient.
+ if (m_cgContext != NULL) {
+ CGContextRelease(m_cgContext);
+ m_cgContext = NULL;
+ }
+ if (m_renderOutput != NULL) {
+ delete[] m_renderOutput;
+ m_renderOutput = NULL;
+ }
+ int rowBytes = width * 4;
+ m_renderOutput = new unsigned char[height * rowBytes];
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ m_cgContext = CGBitmapContextCreate(m_renderOutput, width, height, 8, rowBytes,
+ colorSpace, kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(colorSpace);
+#endif // PLATFORM(CG)
}
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+void GraphicsContext3DInternal::flipVertically(unsigned char* framebuffer,
+ unsigned int width,
+ unsigned int height)
+{
+ unsigned char* scanline = m_scanline;
+ if (scanline == NULL)
+ return;
+ unsigned int rowBytes = width * 4;
+ unsigned int count = height / 2;
+ for (unsigned int i = 0; i < count; i++) {
+ unsigned char* rowA = framebuffer + i * rowBytes;
+ unsigned char* rowB = framebuffer + (height - i - 1) * rowBytes;
+ // FIXME: this is where the multiplication of the alpha
+ // channel into the color buffer will need to occur if the
+ // user specifies the "premultiplyAlpha" flag in the context
+ // creation attributes.
+ memcpy(scanline, rowB, rowBytes);
+ memcpy(rowB, rowA, rowBytes);
+ memcpy(rowA, scanline, rowBytes);
+ }
+}
+#endif
+
void GraphicsContext3DInternal::beginPaint(CanvasRenderingContext3D* context)
{
makeContextCurrent();
@@ -411,124 +523,61 @@
#ifdef RENDER_TO_DEBUGGING_WINDOW
SwapBuffers(m_canvasDC);
#else
- if (m_quadVBO == 0) {
- // Prepare necessary objects for rendering.
- glGenBuffers(1, &m_quadVBO);
- GLfloat vertices[] = {-1.0f, -1.0f,
- 1.0f, -1.0f,
- 1.0f, 1.0f,
- -1.0f, -1.0f,
- 1.0f, 1.0f,
- -1.0f, 1.0f};
- glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- // Vertex shader does vertical flip.
- const GLchar* vertexShaderSrc =
- "attribute vec2 g_Position;\n"
- "varying vec2 texCoord;\n"
- "void main()\n"
- "{\n"
- " texCoord = vec2((g_Position.x + 1.0) * 0.5,\n"
- " (1.0 - g_Position.y) * 0.5);\n"
- " gl_Position = vec4(g_Position, 0.0, 1.0);\n"
- "}\n";
- // Fragment shader does optional premultiplication of alpha
- // into color channels.
- const GLchar* fragmentShaderNoPremultSrc =
- "varying vec2 texCoord;\n"
- "uniform sampler2D texSampler;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = texture2D(texSampler, texCoord);\n"
- "}\n";
- const GLchar* fragmentShaderPremultSrc =
- "varying vec2 texCoord;\n"
- "uniform sampler2D texSampler;\n"
- "void main()\n"
- "{\n"
- " vec4 color = texture2D(texSampler, texCoord);\n"
- " gl_FragColor = vec4(color.r * color.a,\n"
- " color.g * color.a,\n"
- " color.b * color.a,\n"
- " color.a);\n"
- "}\n";
- GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vertexShader, 1, &vertexShaderSrc, NULL);
- checkError();
- GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
- // FIXME: hook up fragmentShaderPremultSrc based on canvas
- // context attributes.
- glShaderSource(fragmentShader, 1, &fragmentShaderNoPremultSrc, NULL);
- checkError();
- m_quadProgram = glCreateProgram();
- glAttachShader(m_quadProgram, vertexShader);
- glAttachShader(m_quadProgram, fragmentShader);
- glBindAttribLocation(m_quadProgram, 0, "g_Position");
- glLinkProgram(m_quadProgram);
- checkError();
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- m_quadTexLocation = glGetUniformLocation(m_quadProgram, "texSampler");
- checkError();
- }
+ // Earlier versions of this code used the GPU to flip the
+ // framebuffer vertically before reading it back for compositing
+ // via software. This code was quite complicated, used a lot of
+ // GPU memory, and didn't provide an obvious speedup. Since this
+ // vertical flip is only a temporary solution anyway until Chrome
+ // is fully GPU composited, it wasn't worth the complexity.
- // We've just rendered a frame into m_texture. Bind m_altTexture
- // as the framebuffer texture, and draw m_texture on to a quad,
- // flipping it vertically and performing alpha premultiplication
- // and color channel swizzling. Then read back the FBO.
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_altTexture, 0);
- glUseProgram(m_quadProgram);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, m_texture);
- glUniform1i(m_quadTexLocation, 0);
- glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
- glEnableVertexAttribArray(0);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
- glDepthMask(false);
- glColorMask(true, true, true, true);
-
HTMLCanvasElement* canvas = context->canvas();
ImageBuffer* imageBuffer = canvas->buffer();
+ unsigned char* pixels = NULL;
+#if PLATFORM(SKIA)
const SkBitmap& bitmap = *imageBuffer->context()->platformContext()->bitmap();
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
- glViewport(0, 0, bitmap.width(), bitmap.height());
+ ASSERT(bitmap.width() == m_cachedWidth);
+ ASSERT(bitmap.height() == m_cachedHeight);
- glDrawArrays(GL_TRIANGLES, 0, 6);
-
// Read back the frame buffer.
SkAutoLockPixels bitmapLock(bitmap);
- glReadPixels(0, 0, bitmap.width(), bitmap.height(), GL_BGRA, GL_UNSIGNED_BYTE, bitmap.getPixels());
+ pixels = static_cast<unsigned char*>(bitmap.getPixels());
+ glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
+#elif PLATFORM(CG)
+ if (m_renderOutput != NULL) {
+ ASSERT(CGBitmapContextGetWidth(m_cgContext) == m_cachedWidth);
+ ASSERT(CGBitmapContextGetHeight(m_cgContext) == m_cachedHeight);
+ pixels = m_renderOutput;
+ glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ }
+#else
+#error Must port to your platform
+#endif
- // Restore the previous FBO state.
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+#ifdef FLIP_FRAMEBUFFER_VERTICALLY
+ if (pixels != NULL)
+ flipVertically(pixels, m_cachedWidth, m_cachedHeight);
+#endif
- // Restore the user's OpenGL state.
- glUseProgram(m_currentProgram);
- const VertexAttribPointerState& state = m_vertexAttribPointerState[0];
- if (state.buffer) {
- glBindBuffer(GL_ARRAY_BUFFER, state.buffer);
- glVertexAttribPointer(state.indx, state.size, state.type, state.normalized,
- state.stride, reinterpret_cast<void*>(static_cast<intptr_t>(state.offset)));
+#if PLATFORM(SKIA)
+ // No further work necessary
+#elif PLATFORM(CG)
+ if (m_renderOutput != NULL) {
+ CGImageRef cgImage = CGBitmapContextCreateImage(m_cgContext);
+ CGRect rect = CGRectMake(0, 0, m_cachedWidth, m_cachedHeight);
+ // We want to completely overwrite the previous frame's
+ // rendering results.
+ CGContextSetBlendMode(imageBuffer->context()->platformContext(),
+ kCGBlendModeCopy);
+ CGContextDrawImage(imageBuffer->context()->platformContext(),
+ rect, cgImage);
+ CGImageRelease(cgImage);
}
- glBindBuffer(GL_ARRAY_BUFFER, m_boundArrayBuffer);
- if (state.enabled)
- glEnableVertexAttribArray(0);
- else
- glDisableVertexAttribArray(0);
- const TextureUnitState& texState = m_textureUnitState[0];
- glBindTexture(texState.target, texState.texture);
- glActiveTexture(m_activeTextureUnit);
- if (m_blendEnabled)
- glEnable(GL_BLEND);
- if (m_depthTestEnabled)
- glEnable(GL_DEPTH_TEST);
- glDepthMask(m_depthMaskEnabled);
- glColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2], m_colorMask[3]);
- glViewport(m_viewport[0], m_viewport[1],
- m_viewport[2], m_viewport[3]);
-#endif // RENDER_TO_DEBUGGING_WINDOW
+#else
+#error Must port to your platform
+#endif
+
+#endif // RENDER_TO_DEBUGGING_WINDOW
}
bool GraphicsContext3DInternal::validateTextureTarget(int target)
@@ -553,7 +602,6 @@
return;
makeContextCurrent();
- m_activeTextureUnit = texture;
glActiveTexture(texture);
}
@@ -576,12 +624,6 @@
makeContextCurrent();
unsigned int textureObject = EXTRACT(texture);
- if (m_activeTextureUnit == 0) {
- TextureUnitState& state = m_textureUnitState[m_activeTextureUnit];
- state.target = target;
- state.texture = textureObject;
- }
-
glBindTexture(target, textureObject);
// FIXME: GL_TEXTURE_WRAP_R isn't exposed in the OpenGL ES 2.0
@@ -620,75 +662,23 @@
usage);
}
-void GraphicsContext3DInternal::colorMask(bool red, bool green, bool blue, bool alpha)
-{
- makeContextCurrent();
- m_colorMask[0] = red;
- m_colorMask[1] = green;
- m_colorMask[2] = blue;
- m_colorMask[3] = alpha;
- glColorMask(red, green, blue, alpha);
-}
-
-void GraphicsContext3DInternal::depthMask(bool flag)
-{
- makeContextCurrent();
- m_depthMaskEnabled = flag;
- glDepthMask(flag);
-}
-
-void GraphicsContext3DInternal::disable(unsigned long cap)
-{
- makeContextCurrent();
- switch (cap) {
- case GL_BLEND:
- m_blendEnabled = false;
- case GL_DEPTH_TEST:
- m_depthTestEnabled = false;
- default:
- break;
- }
- glDisable(cap);
-}
-
void GraphicsContext3DInternal::disableVertexAttribArray(unsigned long index)
{
makeContextCurrent();
- if (index == 0) {
- m_vertexAttribPointerState[0].enabled = false;
+ if (index < NumTrackedPointerStates) {
+ m_vertexAttribPointerState[index].enabled = false;
}
glDisableVertexAttribArray(index);
}
-void GraphicsContext3DInternal::enable(unsigned long cap)
-{
- makeContextCurrent();
- switch (cap) {
- case GL_BLEND:
- m_blendEnabled = true;
- case GL_DEPTH_TEST:
- m_depthTestEnabled = true;
- default:
- break;
- }
- glEnable(cap);
-}
-
void GraphicsContext3DInternal::enableVertexAttribArray(unsigned long index)
{
makeContextCurrent();
- if (index == 0)
- m_vertexAttribPointerState[0].enabled = true;
+ if (index < NumTrackedPointerStates)
+ m_vertexAttribPointerState[index].enabled = true;
glEnableVertexAttribArray(index);
}
-void GraphicsContext3DInternal::useProgram(CanvasProgram* program)
-{
- makeContextCurrent();
- m_currentProgram = EXTRACT(program);
- glUseProgram(m_currentProgram);
-}
-
void GraphicsContext3DInternal::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
unsigned long stride, unsigned long offset)
{
@@ -700,8 +690,8 @@
return;
}
- if (indx == 0) {
- VertexAttribPointerState& state = m_vertexAttribPointerState[0];
+ if (indx < NumTrackedPointerStates) {
+ VertexAttribPointerState& state = m_vertexAttribPointerState[indx];
state.buffer = m_boundArrayBuffer;
state.indx = indx;
state.size = size;
@@ -717,108 +707,102 @@
void GraphicsContext3DInternal::viewportImpl(long x, long y, unsigned long width, unsigned long height)
{
- m_viewport[0] = x;
- m_viewport[1] = y;
- m_viewport[2] = width;
- m_viewport[3] = height;
glViewport(x, y, width, height);
}
// GraphicsContext3D -----------------------------------------------------
-#define GRAPHICS_CONTEXT_NAME GraphicsContext3D
-
/* Helper macros for when we're just wrapping a gl method, so that
* we can avoid having to type this 500 times. Note that these MUST
* NOT BE USED if we need to check any of the parameters.
*/
#define GL_SAME_METHOD_0(glname, name) \
-void GRAPHICS_CONTEXT_NAME::##name() \
+void GraphicsContext3D::name() \
{ \
makeContextCurrent(); gl##glname(); \
}
#define GL_SAME_METHOD_1(glname, name, t1) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1) \
+void GraphicsContext3D::name(t1 a1) \
{ \
makeContextCurrent(); gl##glname(a1); \
}
#define GL_SAME_METHOD_1_X(glname, name, t1) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1) \
+void GraphicsContext3D::name(t1 a1) \
{ \
makeContextCurrent(); gl##glname(EXTRACT(a1)); \
}
#define GL_SAME_METHOD_2(glname, name, t1, t2) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \
+void GraphicsContext3D::name(t1 a1, t2 a2) \
{ \
makeContextCurrent(); gl##glname(a1,a2); \
}
#define GL_SAME_METHOD_2_X12(glname, name, t1, t2) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \
+void GraphicsContext3D::name(t1 a1, t2 a2) \
{ \
makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2)); \
}
#define GL_SAME_METHOD_2_X2(glname, name, t1, t2) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \
+void GraphicsContext3D::name(t1 a1, t2 a2) \
{ \
makeContextCurrent(); gl##glname(a1,EXTRACT(a2)); \
}
#define GL_SAME_METHOD_3(glname, name, t1, t2, t3) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3); \
}
#define GL_SAME_METHOD_3_X12(glname, name, t1, t2, t3) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
{ \
makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2),a3); \
}
#define GL_SAME_METHOD_3_X2(glname, name, t1, t2, t3) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
{ \
makeContextCurrent(); gl##glname(a1,EXTRACT(a2),a3); \
}
#define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3,a4); \
}
#define GL_SAME_METHOD_4_X4(glname, name, t1, t2, t3, t4) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4)); \
}
#define GL_SAME_METHOD_5(glname, name, t1, t2, t3, t4, t5) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5); \
}
#define GL_SAME_METHOD_5_X4(glname, name, t1, t2, t3, t4, t5) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4),a5); \
}
#define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6); \
}
#define GL_SAME_METHOD_8(glname, name, t1, t2, t3, t4, t5, t6, t7, t8) \
-void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
+void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
{ \
makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6,a7,a8); \
}
@@ -1066,10 +1050,7 @@
GL_SAME_METHOD_1(ClearStencil, clearStencil, long)
-void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
-{
- m_internal->colorMask(red, green, blue, alpha);
-}
+GL_SAME_METHOD_4(ColorMask, colorMask, bool, bool, bool, bool)
GL_SAME_METHOD_1_X(CompileShader, compileShader, CanvasShader*)
@@ -1081,10 +1062,7 @@
GL_SAME_METHOD_1(DepthFunc, depthFunc, unsigned long)
-void GraphicsContext3D::depthMask(bool flag)
-{
- m_internal->depthMask(flag);
-}
+GL_SAME_METHOD_1(DepthMask, depthMask, bool)
GL_SAME_METHOD_2(DepthRange, depthRange, double, double)
@@ -1097,10 +1075,7 @@
glDetachShader(EXTRACT(program), EXTRACT(shader));
}
-void GraphicsContext3D::disable(unsigned long cap)
-{
- m_internal->disable(cap);
-}
+GL_SAME_METHOD_1(Disable, disable, unsigned long)
void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
{
@@ -1156,10 +1131,7 @@
reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
}
-void GraphicsContext3D::enable(unsigned long cap)
-{
- m_internal->enable(cap);
-}
+GL_SAME_METHOD_1(Enable, enable, unsigned long)
void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
{
@@ -1680,45 +1652,35 @@
}
}
-int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
- bool flipY, bool premultiplyAlpha)
+// FIXME: this must be changed to refer to the original image data
+// rather than unmultiplying the alpha channel.
+static int texImage2DHelper(unsigned target, unsigned level,
+ int width, int height,
+ int rowBytes,
+ bool flipY,
+ bool premultiplyAlpha,
+ GLenum format,
+ bool skipAlpha,
+ unsigned char* pixels)
{
- CachedImage* cachedImage = image->cachedImage();
- if (cachedImage == NULL) {
- ASSERT_NOT_REACHED();
- return -1;
+ ASSERT(format == GL_RGBA || format == GL_BGRA);
+ GLint internalFormat = GL_RGBA8;
+ if (skipAlpha) {
+ internalFormat = GL_RGB8;
+ // Ignore the alpha channel
+ premultiplyAlpha = true;
}
- Image* img = cachedImage->image();
- NativeImageSkia* skiaImage = img->nativeImageForCurrentFrame();
- if (skiaImage == NULL) {
- ASSERT_NOT_REACHED();
- return -1;
- }
- SkBitmap::Config skiaConfig = skiaImage->config();
- // FIXME: must support more image configurations.
- if (skiaConfig != SkBitmap::kARGB_8888_Config) {
- ASSERT_NOT_REACHED();
- return -1;
- }
- SkBitmap& skiaImageRef = *skiaImage;
- SkAutoLockPixels lock(skiaImageRef);
- int width = skiaImage->width();
- int height = skiaImage->height();
if (flipY) {
// Need to flip images vertically. To avoid making a copy of
// the entire image, we perform a ton of glTexSubImage2D
// calls. FIXME: should rethink this strategy for efficiency.
- glTexImage2D(target, level, GL_RGBA8,
+ glTexImage2D(target, level, internalFormat,
width,
height,
0,
- GL_BGRA,
+ format,
GL_UNSIGNED_BYTE,
NULL);
- unsigned char* pixels =
- reinterpret_cast<unsigned char*>(skiaImage->getPixels());
- int rowBytes = skiaImage->rowBytes();
-
unsigned char* row = NULL;
bool allocatedRow = false;
if (!premultiplyAlpha) {
@@ -1734,7 +1696,7 @@
}
glTexSubImage2D(target, level, 0, height - i - 1,
width, 1,
- GL_BGRA,
+ format,
GL_UNSIGNED_BYTE,
row);
}
@@ -1745,31 +1707,28 @@
// scanline ordering, unlike GL_TEXTURE_2D, so when uploading
// these, the above vertical flip is the wrong thing to do.
if (premultiplyAlpha)
- glTexImage2D(target, level, GL_RGBA8,
+ glTexImage2D(target, level, internalFormat,
width,
height,
0,
- GL_BGRA,
+ format,
GL_UNSIGNED_BYTE,
- skiaImage->getPixels());
+ pixels);
else {
- glTexImage2D(target, level, GL_RGBA8,
+ glTexImage2D(target, level, internalFormat,
width,
height,
0,
- GL_BGRA,
+ format,
GL_UNSIGNED_BYTE,
NULL);
- unsigned char* pixels =
- reinterpret_cast<unsigned char*>(skiaImage->getPixels());
- int rowBytes = skiaImage->rowBytes();
unsigned char* row = new unsigned char[rowBytes];
for (int i = 0; i < height; i++) {
memcpy(row, pixels + (rowBytes * i), rowBytes);
unmultiplyAlpha(row, width);
glTexSubImage2D(target, level, 0, i,
width, 1,
- GL_BGRA,
+ format,
GL_UNSIGNED_BYTE,
row);
}
@@ -1779,6 +1738,74 @@
return 0;
}
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
+ bool flipY, bool premultiplyAlpha)
+{
+ CachedImage* cachedImage = image->cachedImage();
+ if (cachedImage == NULL) {
+ ASSERT_NOT_REACHED();
+ return -1;
+ }
+ Image* img = cachedImage->image();
+ int res = -1;
+#if PLATFORM(SKIA)
+ NativeImageSkia* skiaImage = img->nativeImageForCurrentFrame();
+ if (skiaImage == NULL) {
+ ASSERT_NOT_REACHED();
+ return -1;
+ }
+ SkBitmap::Config skiaConfig = skiaImage->config();
+ // FIXME: must support more image configurations.
+ if (skiaConfig != SkBitmap::kARGB_8888_Config) {
+ ASSERT_NOT_REACHED();
+ return -1;
+ }
+ SkBitmap& skiaImageRef = *skiaImage;
+ SkAutoLockPixels lock(skiaImageRef);
+ int width = skiaImage->width();
+ int height = skiaImage->height();
+ unsigned char* pixels =
+ reinterpret_cast<unsigned char*>(skiaImage->getPixels());
+ int rowBytes = skiaImage->rowBytes();
+ res = texImage2DHelper(target, level,
+ width, height,
+ rowBytes,
+ flipY, premultiplyAlpha,
+ GL_BGRA,
+ false,
+ pixels);
+#elif PLATFORM(CG)
+ CGImageRef cgImage = img->nativeImageForCurrentFrame();
+ if (cgImage == NULL) {
+ ASSERT_NOT_REACHED();
+ return -1;
+ }
+ int width = CGImageGetWidth(cgImage);
+ int height = CGImageGetHeight(cgImage);
+ int rowBytes = width * 4;
+ CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage);
+ bool skipAlpha = (info == kCGImageAlphaNone ||
+ info == kCGImageAlphaNoneSkipLast ||
+ info == kCGImageAlphaNoneSkipFirst);
+ unsigned char* imageData = new unsigned char[height * rowBytes];
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGContextRef tmpContext = CGBitmapContextCreate(imageData, width, height, 8, rowBytes,
+ colorSpace,
+ kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(colorSpace);
+ CGContextDrawImage(tmpContext,
+ CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)),
+ cgImage);
+ CGContextRelease(tmpContext);
+ res = texImage2DHelper(target, level, width, height, rowBytes,
+ flipY, premultiplyAlpha, GL_RGBA, skipAlpha, imageData);
+ delete[] imageData;
+#else
+#error Must port to your platform
+#endif
+ return res;
+}
+
int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
bool flipY, bool premultiplyAlpha)
{
@@ -1956,10 +1983,7 @@
glUniformMatrix4fv(location, size, transpose, value);
}
-void GraphicsContext3D::useProgram(CanvasProgram* program)
-{
- m_internal->useProgram(program);
-}
+GL_SAME_METHOD_1_X(UseProgram, useProgram, CanvasProgram*)
GL_SAME_METHOD_1_X(ValidateProgram, validateProgram, CanvasProgram*)
« no previous file with comments | « third_party/glew/src/glew.c ('k') | webkit/webkit.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698