summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/mac
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/mac')
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.h4
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.mm63
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp168
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h2
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm34
-rw-r--r--WebCore/platform/graphics/mac/WebLayer.mm2
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);
}