diff options
Diffstat (limited to 'WebCore/platform/graphics/mac')
-rw-r--r-- | WebCore/platform/graphics/mac/Canvas3DLayer.h | 4 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/Canvas3DLayer.mm | 63 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp | 168 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsLayerCA.h | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsLayerCA.mm | 34 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/WebLayer.mm | 2 |
6 files changed, 216 insertions, 57 deletions
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/Canvas3DLayer.h index 6c65676..122ef39 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.h +++ b/WebCore/platform/graphics/mac/Canvas3DLayer.h @@ -41,7 +41,9 @@ namespace WebCore { GLuint m_texture; } --(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture; +- (id)initWithContext:(CGLContextObj)context texture:(GLuint)texture; + +- (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace; @end diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm index 545c58b..94819d4 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.mm +++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm @@ -33,6 +33,8 @@ #import "GraphicsLayer.h" #import <QuartzCore/QuartzCore.h> #import <OpenGL/OpenGL.h> +#import <wtf/RetainPtr.h> +#include <wtf/FastMalloc.h> using namespace WebCore; @@ -48,19 +50,14 @@ using namespace WebCore; -(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { - CGLPixelFormatAttribute attribs[] = - { - (CGLPixelFormatAttribute) kCGLPFAAccelerated, - (CGLPixelFormatAttribute) kCGLPFAColorSize, (CGLPixelFormatAttribute) 32, - (CGLPixelFormatAttribute) kCGLPFADisplayMask, (CGLPixelFormatAttribute) mask, - (CGLPixelFormatAttribute) 0 - }; - - CGLPixelFormatObj pixelFormatObj; - GLint numPixelFormats; - - CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats); - return pixelFormatObj; + // FIXME: The mask param tells you which display (on a multi-display system) + // is to be used. But since we are now getting the pixel format from the + // Canvas CGL context, we don't use it. This seems to do the right thing on + // one multi-display system. But there may be cases where this is not the case. + // If needed we will have to set the display mask in the Canvas CGLContext and + // make sure it matches. + UNUSED_PARAM(mask); + return CGLRetainPixelFormat(CGLGetPixelFormat(m_contextObj)); } -(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat @@ -72,6 +69,10 @@ using namespace WebCore; -(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { + CGLSetCurrentContext(m_contextObj); + glFinish(); + CGLSetCurrentContext(glContext); + CGRect frame = [self frame]; // draw the FBO into the layer @@ -103,6 +104,42 @@ using namespace WebCore; [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp]; } +static void freeData(void *, const void *data, size_t /* size */) +{ + fastFree(const_cast<void *>(data)); +} + +-(CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace +{ + CGLSetCurrentContext(m_contextObj); + + RetainPtr<CGColorSpaceRef> imageColorSpace = colorSpace; + if (!imageColorSpace) + imageColorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); + + CGRect layerBounds = CGRectIntegral([self bounds]); + + size_t width = layerBounds.size.width; + size_t height = layerBounds.size.height; + + size_t rowBytes = (width * 4 + 15) & ~15; + size_t dataSize = rowBytes * height; + void* data = fastMalloc(dataSize); + if (!data) + return 0; + + glPixelStorei(GL_PACK_ROW_LENGTH, rowBytes / 4); + glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); + + CGDataProviderRef provider = CGDataProviderCreateWithData(0, data, dataSize, freeData); + CGImageRef image = CGImageCreate(width, height, 8, 32, rowBytes, imageColorSpace.get(), + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, + provider, 0, true, + kCGRenderingIntentDefault); + CGDataProviderRelease(provider); + return image; +} + @end @implementation Canvas3DLayer(WebLayerAdditions) diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index cd66445..47617d8 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -30,9 +30,10 @@ #include "GraphicsContext3D.h" #include "CachedImage.h" +#include "CanvasActiveInfo.h" +#include "CanvasArray.h" #include "CanvasBuffer.h" #include "CanvasFramebuffer.h" -#include "CanvasArray.h" #include "CanvasFloatArray.h" #include "CanvasIntArray.h" #include "CanvasObject.h" @@ -49,29 +50,91 @@ #include "WebKitCSSMatrix.h" #include <CoreGraphics/CGBitmapContext.h> +#include <OpenGL/CGLRenderers.h> namespace WebCore { -GraphicsContext3D::GraphicsContext3D() +static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBits, int depthBits, bool accelerated, bool supersample, bool closest) { - CGLPixelFormatAttribute attribs[] = - { - (CGLPixelFormatAttribute) kCGLPFAAccelerated, - (CGLPixelFormatAttribute) kCGLPFAColorSize, (CGLPixelFormatAttribute) 32, - (CGLPixelFormatAttribute) kCGLPFADepthSize, (CGLPixelFormatAttribute) 32, - (CGLPixelFormatAttribute) kCGLPFASupersample, - (CGLPixelFormatAttribute) 0 - }; + attribs.clear(); - CGLPixelFormatObj pixelFormatObj; - GLint numPixelFormats; + attribs.append(kCGLPFAColorSize); + attribs.append(static_cast<CGLPixelFormatAttribute>(colorBits)); + attribs.append(kCGLPFADepthSize); + attribs.append(static_cast<CGLPixelFormatAttribute>(depthBits)); - CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats); - - CGLCreateContext(pixelFormatObj, 0, &m_contextObj); + if (accelerated) + attribs.append(kCGLPFAAccelerated); + else { + attribs.append(kCGLPFARendererID); + attribs.append(static_cast<CGLPixelFormatAttribute>(kCGLRendererGenericFloatID)); + } + + if (supersample) + attribs.append(kCGLPFASupersample); + + if (closest) + attribs.append(kCGLPFAClosestPolicy); + + attribs.append(static_cast<CGLPixelFormatAttribute>(0)); +} + +PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create() +{ + OwnPtr<GraphicsContext3D> context(new GraphicsContext3D()); + return context->m_contextObj ? context.release() : 0; +} + +GraphicsContext3D::GraphicsContext3D() + : m_contextObj(0) + , m_texture(0) + , m_fbo(0) + , m_depthBuffer(0) +{ + Vector<CGLPixelFormatAttribute> attribs; + CGLPixelFormatObj pixelFormatObj = 0; + GLint numPixelFormats = 0; + + // We will try: + // + // 1) 32 bit RGBA/32 bit depth/accelerated/supersampled + // 2) 32 bit RGBA/32 bit depth/accelerated + // 3) 32 bit RGBA/16 bit depth/accelerated + // 4) closest to 32 bit RGBA/16 bit depth/software renderer + // + // If none of that works, we simply fail and set m_contextObj to 0. + + setPixelFormat(attribs, 32, 32, true, true, false); + CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); + if (numPixelFormats == 0) { + setPixelFormat(attribs, 32, 32, true, false, false); + CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); + + if (numPixelFormats == 0) { + setPixelFormat(attribs, 32, 16, true, false, false); + CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); + + if (numPixelFormats == 0) { + setPixelFormat(attribs, 32, 16, false, false, true); + CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); + + if (numPixelFormats == 0) { + // Could not find an acceptable renderer - fail + return; + } + } + } + } + CGLError err = CGLCreateContext(pixelFormatObj, 0, &m_contextObj); CGLDestroyPixelFormat(pixelFormatObj); + if (err != kCGLNoError || !m_contextObj) { + // Could not create the context - fail + m_contextObj = 0; + return; + } + // Set the current context to the one given to us. CGLSetCurrentContext(m_contextObj); @@ -102,12 +165,14 @@ GraphicsContext3D::GraphicsContext3D() GraphicsContext3D::~GraphicsContext3D() { - CGLSetCurrentContext(m_contextObj); - ::glDeleteRenderbuffersEXT(1, & m_depthBuffer); - ::glDeleteTextures(1, &m_texture); - ::glDeleteFramebuffersEXT(1, &m_fbo); - CGLSetCurrentContext(0); - CGLDestroyContext(m_contextObj); + if (m_contextObj) { + CGLSetCurrentContext(m_contextObj); + ::glDeleteRenderbuffersEXT(1, & m_depthBuffer); + ::glDeleteTextures(1, &m_texture); + ::glDeleteFramebuffersEXT(1, &m_fbo); + CGLSetCurrentContext(0); + CGLDestroyContext(m_contextObj); + } } void GraphicsContext3D::checkError() const @@ -135,7 +200,7 @@ void GraphicsContext3D::endPaint() void GraphicsContext3D::reshape(int width, int height) { - if (width == m_currentWidth && height == m_currentHeight) + if (width == m_currentWidth && height == m_currentHeight || !m_contextObj) return; m_currentWidth = width; @@ -167,6 +232,9 @@ void GraphicsContext3D::reshape(int width, int height) static inline void ensureContext(CGLContextObj context) { + if (!context) + return; + CGLContextObj currentContext = CGLGetCurrentContext(); if (currentContext != context) CGLSetCurrentContext(context); @@ -442,6 +510,46 @@ void GraphicsContext3D::generateMipmap(unsigned long target) ::glGenerateMipmapEXT(target); } +bool GraphicsContext3D::getActiveAttrib(CanvasProgram* program, unsigned long index, ActiveInfo& info) +{ + if (!program->object()) + return false; + ensureContext(m_contextObj); + GLint maxAttributeSize = 0; + ::glGetProgramiv(static_cast<GLuint>(program->object()), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize); + GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination + GLsizei nameLength = 0; + GLint size = 0; + GLenum type = 0; + ::glGetActiveAttrib(static_cast<GLuint>(program->object()), index, maxAttributeSize, &nameLength, &size, &type, name); + if (!nameLength) + return false; + info.name = String(name, nameLength); + info.type = type; + info.size = size; + return true; +} + +bool GraphicsContext3D::getActiveUniform(CanvasProgram* program, unsigned long index, ActiveInfo& info) +{ + if (!program->object()) + return false; + ensureContext(m_contextObj); + GLint maxUniformSize = 0; + ::glGetProgramiv(static_cast<GLuint>(program->object()), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); + GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination + GLsizei nameLength = 0; + GLint size = 0; + GLenum type = 0; + ::glGetActiveUniform(static_cast<GLuint>(program->object()), index, maxUniformSize, &nameLength, &size, &type, name); + if (!nameLength) + return false; + info.name = String(name, nameLength); + info.type = type; + info.size = size; + return true; +} + int GraphicsContext3D::getAttribLocation(CanvasProgram* program, const String& name) { if (!program) @@ -556,6 +664,22 @@ void GraphicsContext3D::polygonOffset(double factor, double units) ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units)); } +PassRefPtr<CanvasArray> GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type) +{ + ensureContext(m_contextObj); + + // FIXME: For now we only accept GL_UNSIGNED_BYTE/GL_RGBA. In reality OpenGL ES 2.0 accepts that pair and one other + // as specified by GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. But for now we will + // not accept those. + // FIXME: Also, we should throw when an unacceptable value is passed + if (type != GL_UNSIGNED_BYTE || format != GL_RGBA) + return 0; + + RefPtr<CanvasUnsignedByteArray> array = CanvasUnsignedByteArray::create(width * height * 4); + ::glReadPixels(x, y, width, height, format, type, (GLvoid*) array->data()); + return array; +} + void GraphicsContext3D::releaseShaderCompiler() { // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index d0e1108..8cf51b4 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -110,10 +110,8 @@ public: virtual PlatformLayer* platformLayer() const; -#ifndef NDEBUG virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); -#endif virtual void setGeometryOrientation(CompositingCoordinatesOrientation); diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index e9960f1..b351956 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -274,7 +274,6 @@ static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction& tim return 0; } -#ifndef NDEBUG static void setLayerBorderColor(PlatformLayer* layer, const Color& color) { CGColorRef borderColor = createCGColor(color); @@ -286,7 +285,6 @@ static void clearBorderColor(PlatformLayer* layer) { [layer setBorderColor:nil]; } -#endif static void setLayerBackgroundColor(PlatformLayer* layer, const Color& color) { @@ -317,7 +315,6 @@ GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoord return CompositingCoordinatesBottomUp; } -#ifndef NDEBUG bool GraphicsLayer::showDebugBorders() { static bool showDebugBorders = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreLayerBorders"]; @@ -329,7 +326,6 @@ bool GraphicsLayer::showRepaintCounter() static bool showRepaintCounter = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreLayerRepaintCounter"]; return showRepaintCounter; } -#endif static NSDictionary* nullActionsDictionary() { @@ -373,9 +369,7 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) setContentsOrientation(defaultContentsOrientation()); #endif -#ifndef NDEBUG updateDebugIndicators(); -#endif m_animationDelegate.adoptNS([[WebAnimationDelegate alloc] init]); [m_animationDelegate.get() setLayer:this]; @@ -964,9 +958,7 @@ void GraphicsLayerCA::updateChildrenTransform() void GraphicsLayerCA::updateMasksToBounds() { [m_layer.get() setMasksToBounds:m_masksToBounds]; -#ifndef NDEBUG updateDebugIndicators(); -#endif } void GraphicsLayerCA::updateContentsOpaque() @@ -1051,9 +1043,7 @@ void GraphicsLayerCA::updateLayerDrawsContent() else [m_layer.get() setContents:nil]; -#ifndef NDEBUG updateDebugIndicators(); -#endif } void GraphicsLayerCA::updateLayerBackgroundColor() @@ -1245,6 +1235,21 @@ void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedP [layer addAnimation:caAnim forKey:animationName]; } +// Workaround for <rdar://problem/7311367> +static void bug7311367Workaround(CALayer* transformLayer, const TransformationMatrix& transform) +{ + if (!transformLayer) + return; + + CATransform3D caTransform; + copyTransform(caTransform, transform); + caTransform.m41 += 1; + [transformLayer setTransform:caTransform]; + + caTransform.m41 -= 1; + [transformLayer setTransform:caTransform]; +} + bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, int index) { PlatformLayer* layer = animatedLayer(property); @@ -1255,10 +1260,11 @@ bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, int return false; [layer removeAnimationForKey:animationName]; + + bug7311367Workaround(m_transformLayer.get(), m_transform); return true; } - static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimation* to) { [to setBeginTime:[from beginTime]]; @@ -1679,7 +1685,6 @@ PlatformLayer* GraphicsLayerCA::platformLayer() const return primaryLayer(); } -#ifndef NDEBUG void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) { BEGIN_BLOCK_OBJC_EXCEPTIONS @@ -1706,7 +1711,6 @@ void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) END_BLOCK_OBJC_EXCEPTIONS } -#endif // NDEBUG bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const { @@ -1784,9 +1788,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) // need to tell new layer to draw itself setNeedsDisplay(); -#ifndef NDEBUG updateDebugIndicators(); -#endif } GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const @@ -1830,12 +1832,10 @@ void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer) } else [contentsLayer setAnchorPoint:CGPointZero]; -#ifndef NDEBUG if (showDebugBorders()) { setLayerBorderColor(contentsLayer, Color(0, 0, 128, 180)); [contentsLayer setBorderWidth:1.0f]; } -#endif } void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm index 2647466..56b28e6 100644 --- a/WebCore/platform/graphics/mac/WebLayer.mm +++ b/WebCore/platform/graphics/mac/WebLayer.mm @@ -80,7 +80,6 @@ using namespace WebCore; } #endif -#ifndef NDEBUG if (layerContents->showRepaintCounter()) { bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]]; @@ -107,7 +106,6 @@ using namespace WebCore; CGContextRestoreGState(context); } -#endif CGContextRestoreGState(context); } |