summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/mac
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-10-08 17:19:54 +0100
committerSteve Block <steveblock@google.com>2009-10-20 00:41:58 +0100
commit231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch)
treea6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/platform/graphics/mac
parente196732677050bd463301566a68a643b6d14b907 (diff)
downloadexternal_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/platform/graphics/mac')
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.h50
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.mm123
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.cpp2
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp12
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm27
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm47
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp1698
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm15
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h29
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm127
-rw-r--r--WebCore/platform/graphics/mac/ImageMac.mm9
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h6
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm42
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm31
14 files changed, 2145 insertions, 73 deletions
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/Canvas3DLayer.h
new file mode 100644
index 0000000..6c65676
--- /dev/null
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Canvas3DLayer_h
+#define Canvas3DLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#import "WebLayer.h"
+
+namespace WebCore {
+ class GraphicsLayer;
+}
+
+@interface Canvas3DLayer : CAOpenGLLayer
+{
+ WebCore::GraphicsLayer* m_layerOwner;
+ CGLContextObj m_contextObj;
+ GLuint m_texture;
+}
+
+-(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture;
+
+@end
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // Canvas3DLayer_h
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
new file mode 100644
index 0000000..545c58b
--- /dev/null
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#if ENABLE(3D_CANVAS)
+
+#import "Canvas3DLayer.h"
+
+#import "GraphicsLayer.h"
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGL/OpenGL.h>
+
+using namespace WebCore;
+
+@implementation Canvas3DLayer
+
+-(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture
+{
+ m_contextObj = context;
+ m_texture = texture;
+ self = [super init];
+ return self;
+}
+
+-(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;
+}
+
+-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+{
+ CGLContextObj contextObj;
+ CGLCreateContext(pixelFormat, m_contextObj, &contextObj);
+ return contextObj;
+}
+
+-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
+{
+ CGRect frame = [self frame];
+
+ // draw the FBO into the layer
+ glViewport(0, 0, frame.size.width, frame.size.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1, 1, -1, 1, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+
+ glBegin(GL_TRIANGLE_FAN);
+ glTexCoord2f(0, 0);
+ glVertex2f(-1, -1);
+ glTexCoord2f(1, 0);
+ glVertex2f(1, -1);
+ glTexCoord2f(1, 1);
+ glVertex2f(1, 1);
+ glTexCoord2f(0, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ // Call super to finalize the drawing. By default all it does is call glFlush().
+ [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
+}
+
+@end
+
+@implementation Canvas3DLayer(WebLayerAdditions)
+
+-(void)setLayerOwner:(GraphicsLayer*)aLayer
+{
+ m_layerOwner = aLayer;
+}
+
+-(GraphicsLayer*)layerOwner
+{
+ return m_layerOwner;
+}
+
+@end
+
+#endif // ENABLE(3D_CANVAS)
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/CoreTextController.cpp
index 05f29b5..b2682e4 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/CoreTextController.cpp
@@ -365,7 +365,7 @@ void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsig
RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes()));
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
RetainPtr<CTTypesetterRef> typesetter;
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index e40bbab..5e72101 100644
--- a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -46,11 +46,13 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
ATSFontContainerRef containerRef = 0;
ATSFontRef fontRef = 0;
+ RetainPtr<CGFontRef> cgFontRef;
+
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
RetainPtr<CFDataRef> bufferData(AdoptCF, buffer->createCFData());
RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(bufferData.get()));
- CGFontRef cgFontRef = CGFontCreateWithDataProvider(dataProvider.get());
+ cgFontRef.adoptCF(CGFontCreateWithDataProvider(dataProvider.get()));
if (!cgFontRef)
return 0;
#else
@@ -75,13 +77,11 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
return 0;
}
- CGFontRef cgFontRef = CGFontCreateWithPlatformFont(&fontRef);
+ cgFontRef.adoptCF(CGFontCreateWithPlatformFont(&fontRef));
#ifndef BUILDING_ON_TIGER
// Workaround for <rdar://problem/5675504>.
- if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef)) {
- CFRelease(cgFontRef);
+ if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef.get()))
cgFontRef = 0;
- }
#endif
if (!cgFontRef) {
ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
@@ -89,7 +89,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
}
#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- return new FontCustomPlatformData(containerRef, fontRef, cgFontRef);
+ return new FontCustomPlatformData(containerRef, fontRef, cgFontRef.releaseRef());
}
}
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index df9494a..b2b9a5c 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -50,10 +50,33 @@ bool Font::canReturnFallbackFontsForComplexText()
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
+ bool newShouldUseFontSmoothing = shouldUseSmoothing();
+
+ switch(fontDescription().fontSmoothing()) {
+ case Antialiased: {
+ context->setShouldAntialias(true);
+ newShouldUseFontSmoothing = false;
+ break;
+ }
+ case SubpixelAntialiased: {
+ context->setShouldAntialias(true);
+ newShouldUseFontSmoothing = true;
+ break;
+ }
+ case NoSmoothing: {
+ context->setShouldAntialias(false);
+ newShouldUseFontSmoothing = false;
+ break;
+ }
+ case AutoSmoothing: {
+ // For the AutoSmooth case, don't do anything! Keep the default settings.
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
- bool newShouldUseFontSmoothing = shouldUseSmoothing();
-
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
index 051abb7..409bda4 100644
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ b/WebCore/platform/graphics/mac/FontMacATSUI.mm
@@ -105,12 +105,12 @@ static bool fontHasMirroringInfo(ATSUFontID fontID)
return false;
}
-static void disableLigatures(const SimpleFontData* fontData)
+static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode)
{
// Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
// in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
// See bugzilla 5166.
- if (fontData->platformData().allowsLigatures())
+ if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
return;
ATSUFontFeatureType featureTypes[] = { kLigaturesType };
@@ -120,7 +120,7 @@ static void disableLigatures(const SimpleFontData* fontData)
LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", status);
}
-static void initializeATSUStyle(const SimpleFontData* fontData)
+static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
{
if (fontData->m_ATSUStyleInitialized)
return;
@@ -141,19 +141,28 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
- // Turn off automatic kerning until it is supported in the CG code path (bug 6136)
- Fract kerningInhibitFactor = FloatToFract(1.0);
- ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
- ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &transform, &kerningInhibitFactor };
- status = ATSUSetAttributes(fontData->m_ATSUStyle, 4, styleTags, styleSizes, styleValues);
- if (status != noErr)
- LOG_ERROR("ATSUSetAttributes failed (%d)", status);
+ bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+ if (!allowKerning) {
+ // Turn off automatic kerning until it is supported in the CG code path (bug 6136)
+ Fract kerningInhibitFactor = FloatToFract(1.0);
+ ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
+ ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &transform, &kerningInhibitFactor };
+ status = ATSUSetAttributes(fontData->m_ATSUStyle, 4, styleTags, styleSizes, styleValues);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetAttributes failed (%d)", status);
+ } else {
+ ATSUAttributeTag styleTags[3] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag };
+ ATSUAttributeValuePtr styleValues[3] = { &fontSize, &fontID, &transform, };
+ status = ATSUSetAttributes(fontData->m_ATSUStyle, 3, styleTags, styleSizes, styleValues);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetAttributes failed (%d)", status);
+ }
fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
// Turn off ligatures such as 'fi' to match the CG code path's behavior, until bug 6135 is fixed.
- disableLigatures(fontData);
+ disableLigatures(fontData, textMode);
fontData->m_ATSUStyleInitialized = true;
}
@@ -329,7 +338,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
OSStatus status;
ATSULayoutOperationOverrideSpecifier overrideSpecifier;
- initializeATSUStyle(fontData);
+ initializeATSUStyle(fontData, m_font->fontDescription().textRenderingMode());
// FIXME: This is currently missing the following required features that the CoreGraphics code path has:
// - \n, \t, and nonbreaking space render as a space.
@@ -393,7 +402,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);
substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;
if (substituteFontData) {
- initializeATSUStyle(substituteFontData);
+ initializeATSUStyle(substituteFontData, m_font->fontDescription().textRenderingMode());
if (substituteFontData->m_ATSUStyle)
ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);
} else
@@ -412,7 +421,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
if (i == substituteOffset || i == substituteOffset + substituteLength) {
if (isSmallCap) {
isSmallCap = false;
- initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()));
+ initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()), m_font->fontDescription().textRenderingMode());
ATSUSetRunStyle(layout, r->smallCapsFontData(m_font->fontDescription())->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
}
if (i == substituteOffset && substituteLength > 0)
@@ -456,7 +465,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
} else {
if (isSmallCap) {
isSmallCap = false;
- initializeATSUStyle(smallCapsData);
+ initializeATSUStyle(smallCapsData, m_font->fontDescription().textRenderingMode());
ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
}
m_fonts[i] = r;
@@ -504,8 +513,8 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint&
firstGlyphBounds = zeroTrapezoid;
}
- float beforeWidth = MIN(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
- float afterWidth = MAX(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
+ float beforeWidth = min(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
+ float afterWidth = max(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
FloatRect rect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
@@ -591,8 +600,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
if (actualNumBounds != 1)
LOG_ERROR("unexpected result from ATSUGetGlyphBounds(): actualNumBounds(%d) != 1", actualNumBounds);
- return MAX(FixedToFloat(firstGlyphBounds.upperRight.x), FixedToFloat(firstGlyphBounds.lowerRight.x)) -
- MIN(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
+ return max(FixedToFloat(firstGlyphBounds.upperRight.x), FixedToFloat(firstGlyphBounds.lowerRight.x)) -
+ min(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
}
int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool /*includePartialGlyphs*/) const
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
new file mode 100644
index 0000000..cd66445
--- /dev/null
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
@@ -0,0 +1,1698 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "GraphicsContext3D.h"
+
+#include "CachedImage.h"
+#include "CanvasBuffer.h"
+#include "CanvasFramebuffer.h"
+#include "CanvasArray.h"
+#include "CanvasFloatArray.h"
+#include "CanvasIntArray.h"
+#include "CanvasObject.h"
+#include "CanvasProgram.h"
+#include "CanvasRenderbuffer.h"
+#include "CanvasShader.h"
+#include "CanvasTexture.h"
+#include "CanvasUnsignedByteArray.h"
+#include "CString.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "ImageBuffer.h"
+#include "NotImplemented.h"
+#include "WebKitCSSMatrix.h"
+
+#include <CoreGraphics/CGBitmapContext.h>
+
+namespace WebCore {
+
+GraphicsContext3D::GraphicsContext3D()
+{
+ CGLPixelFormatAttribute attribs[] =
+ {
+ (CGLPixelFormatAttribute) kCGLPFAAccelerated,
+ (CGLPixelFormatAttribute) kCGLPFAColorSize, (CGLPixelFormatAttribute) 32,
+ (CGLPixelFormatAttribute) kCGLPFADepthSize, (CGLPixelFormatAttribute) 32,
+ (CGLPixelFormatAttribute) kCGLPFASupersample,
+ (CGLPixelFormatAttribute) 0
+ };
+
+ CGLPixelFormatObj pixelFormatObj;
+ GLint numPixelFormats;
+
+ CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats);
+
+ CGLCreateContext(pixelFormatObj, 0, &m_contextObj);
+
+ CGLDestroyPixelFormat(pixelFormatObj);
+
+ // Set the current context to the one given to us.
+ CGLSetCurrentContext(m_contextObj);
+
+ // create a texture to render into
+ ::glGenTextures(1, &m_texture);
+ ::glBindTexture(GL_TEXTURE_2D, m_texture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+
+ // create an FBO
+ ::glGenFramebuffersEXT(1, &m_fbo);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+
+ ::glGenRenderbuffersEXT(1, &m_depthBuffer);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
+ ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 1, 1);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
+
+ ::glClearColor(0, 0, 0, 0);
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+ CGLSetCurrentContext(m_contextObj);
+ ::glDeleteRenderbuffersEXT(1, & m_depthBuffer);
+ ::glDeleteTextures(1, &m_texture);
+ ::glDeleteFramebuffersEXT(1, &m_fbo);
+ CGLSetCurrentContext(0);
+ CGLDestroyContext(m_contextObj);
+}
+
+void GraphicsContext3D::checkError() const
+{
+ // FIXME: This needs to only be done in the debug context. It will probably throw an exception
+ // on error and print the error message to the debug console
+ GLenum error = ::glGetError();
+ if (error != GL_NO_ERROR)
+ notImplemented();
+}
+
+void GraphicsContext3D::makeContextCurrent()
+{
+ CGLSetCurrentContext(m_contextObj);
+}
+
+void GraphicsContext3D::beginPaint(CanvasRenderingContext3D* context)
+{
+ UNUSED_PARAM(context);
+}
+
+void GraphicsContext3D::endPaint()
+{
+}
+
+void GraphicsContext3D::reshape(int width, int height)
+{
+ if (width == m_currentWidth && height == m_currentHeight)
+ return;
+
+ m_currentWidth = width;
+ m_currentHeight = height;
+
+ CGLSetCurrentContext(m_contextObj);
+
+ ::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, 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);
+ ::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) {
+ // FIXME: cleanup
+ notImplemented();
+ }
+
+ ::glViewport(0, 0, m_currentWidth, m_currentHeight);
+ ::glClear(GL_COLOR_BUFFER_BIT);
+ ::glFlush();
+}
+
+static inline void ensureContext(CGLContextObj context)
+{
+ CGLContextObj currentContext = CGLGetCurrentContext();
+ if (currentContext != context)
+ CGLSetCurrentContext(context);
+}
+
+void GraphicsContext3D::activeTexture(unsigned long texture)
+{
+ ensureContext(m_contextObj);
+ ::glActiveTexture(texture);
+}
+
+void GraphicsContext3D::attachShader(CanvasProgram* program, CanvasShader* shader)
+{
+ if (!program || !shader)
+ return;
+ ensureContext(m_contextObj);
+ ::glAttachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::bindAttribLocation(CanvasProgram* program, unsigned long index, const String& name)
+{
+ if (!program)
+ return;
+ ensureContext(m_contextObj);
+ ::glBindAttribLocation((GLuint) program->object(), index, name.utf8().data());
+}
+
+void GraphicsContext3D::bindBuffer(unsigned long target, CanvasBuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindBuffer(target, buffer ? (GLuint) buffer->object() : 0);
+}
+
+
+void GraphicsContext3D::bindFramebuffer(unsigned long target, CanvasFramebuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindFramebufferEXT(target, buffer ? (GLuint) buffer->object() : m_fbo);
+}
+
+void GraphicsContext3D::bindRenderbuffer(unsigned long target, CanvasRenderbuffer* renderbuffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindBuffer(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
+}
+
+
+void GraphicsContext3D::bindTexture(unsigned long target, CanvasTexture* texture)
+{
+ ensureContext(m_contextObj);
+ ::glBindTexture(target, texture ? (GLuint) texture->object() : 0);
+}
+
+void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
+}
+
+void GraphicsContext3D::blendEquation( unsigned long mode )
+{
+ ensureContext(m_contextObj);
+ ::glBlendEquation(mode);
+}
+
+void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+
+void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor)
+{
+ ensureContext(m_contextObj);
+ ::glBlendFunc(sfactor, dfactor);
+}
+
+void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage)
+{
+ ensureContext(m_contextObj);
+ ::glBufferData(target, size, 0, usage);
+}
+void GraphicsContext3D::bufferData(unsigned long target, CanvasArray* array, unsigned long usage)
+{
+ if (!array || !array->length())
+ return;
+
+ ensureContext(m_contextObj);
+ ::glBufferData(target, array->sizeInBytes(), array->baseAddress(), usage);
+}
+
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, CanvasArray* array)
+{
+ if (!array || !array->length())
+ return;
+
+ ensureContext(m_contextObj);
+ ::glBufferSubData(target, offset, array->sizeInBytes(), array->baseAddress());
+}
+
+unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
+{
+ ensureContext(m_contextObj);
+ return ::glCheckFramebufferStatusEXT(target);
+}
+
+void GraphicsContext3D::clearColor(double r, double g, double b, double a)
+{
+ ensureContext(m_contextObj);
+ ::glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a));
+}
+
+void GraphicsContext3D::clear(unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glClear(mask);
+}
+
+void GraphicsContext3D::clearDepth(double depth)
+{
+ ensureContext(m_contextObj);
+ ::glClearDepth(depth);
+}
+
+void GraphicsContext3D::clearStencil(long s)
+{
+ ensureContext(m_contextObj);
+ ::glClearStencil(s);
+}
+
+void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
+{
+ ensureContext(m_contextObj);
+ ::glColorMask(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::compileShader(CanvasShader* shader)
+{
+ if (!shader)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glCompileShader((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)
+{
+ ensureContext(m_contextObj);
+ ::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)
+{
+ ensureContext(m_contextObj);
+ ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+}
+
+void GraphicsContext3D::cullFace(unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glCullFace(mode);
+}
+
+void GraphicsContext3D::depthFunc(unsigned long func)
+{
+ ensureContext(m_contextObj);
+ ::glDepthFunc(func);
+}
+
+void GraphicsContext3D::depthMask(bool flag)
+{
+ ensureContext(m_contextObj);
+ ::glDepthMask(flag);
+}
+
+void GraphicsContext3D::depthRange(double zNear, double zFar)
+{
+ ensureContext(m_contextObj);
+ ::glDepthRange(zNear, zFar);
+}
+
+void GraphicsContext3D::detachShader(CanvasProgram* program, CanvasShader* shader)
+{
+ if (!program || !shader)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glDetachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::disable(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ ::glDisable(cap);
+}
+
+void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
+{
+ ensureContext(m_contextObj);
+ ::glDisableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
+{
+ ensureContext(m_contextObj);
+ ::glDrawArrays(mode, first, count);
+}
+
+void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset)
+{
+ ensureContext(m_contextObj);
+ ::glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::enable(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ ::glEnable(cap);
+}
+
+void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
+{
+ ensureContext(m_contextObj);
+ ::glEnableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::finish()
+{
+ ensureContext(m_contextObj);
+ ::glFinish();
+}
+
+void GraphicsContext3D::flush()
+{
+ ensureContext(m_contextObj);
+ ::glFlush();
+}
+
+void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, CanvasRenderbuffer* buffer)
+{
+ if (!buffer)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, (GLuint) buffer->object());
+}
+
+void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, CanvasTexture* texture, long level)
+{
+ if (!texture)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glFramebufferTexture2DEXT(target, attachment, textarget, (GLuint) texture->object(), level);
+}
+
+void GraphicsContext3D::frontFace(unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glFrontFace(mode);
+}
+
+void GraphicsContext3D::generateMipmap(unsigned long target)
+{
+ ensureContext(m_contextObj);
+ ::glGenerateMipmapEXT(target);
+}
+
+int GraphicsContext3D::getAttribLocation(CanvasProgram* program, const String& name)
+{
+ if (!program)
+ return -1;
+
+ ensureContext(m_contextObj);
+ return ::glGetAttribLocation((GLuint) program->object(), name.utf8().data());
+}
+
+unsigned long GraphicsContext3D::getError()
+{
+ ensureContext(m_contextObj);
+ return ::glGetError();
+}
+
+String GraphicsContext3D::getString(unsigned long name)
+{
+ ensureContext(m_contextObj);
+ return String((const char*) ::glGetString(name));
+}
+
+void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glHint(target, mode);
+}
+
+bool GraphicsContext3D::isBuffer(CanvasBuffer* buffer)
+{
+ if (!buffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsBuffer((GLuint) buffer->object());
+}
+
+bool GraphicsContext3D::isEnabled(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ return ::glIsEnabled(cap);
+}
+
+bool GraphicsContext3D::isFramebuffer(CanvasFramebuffer* framebuffer)
+{
+ if (!framebuffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsFramebufferEXT((GLuint) framebuffer->object());
+}
+
+bool GraphicsContext3D::isProgram(CanvasProgram* program)
+{
+ if (!program)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsProgram((GLuint) program->object());
+}
+
+bool GraphicsContext3D::isRenderbuffer(CanvasRenderbuffer* renderbuffer)
+{
+ if (!renderbuffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsRenderbufferEXT((GLuint) renderbuffer->object());
+}
+
+bool GraphicsContext3D::isShader(CanvasShader* shader)
+{
+ if (!shader)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsShader((GLuint) shader->object());
+}
+
+bool GraphicsContext3D::isTexture(CanvasTexture* texture)
+{
+ if (!texture)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsTexture((GLuint) texture->object());
+}
+
+void GraphicsContext3D::lineWidth(double width)
+{
+ ensureContext(m_contextObj);
+ ::glLineWidth(static_cast<float>(width));
+}
+
+void GraphicsContext3D::linkProgram(CanvasProgram* program)
+{
+ if (!program)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glLinkProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::pixelStorei(unsigned long pname, long param)
+{
+ ensureContext(m_contextObj);
+ ::glPixelStorei(pname, param);
+}
+
+void GraphicsContext3D::polygonOffset(double factor, double units)
+{
+ ensureContext(m_contextObj);
+ ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units));
+}
+
+void GraphicsContext3D::releaseShaderCompiler()
+{
+ // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants
+ ensureContext(m_contextObj);
+ //::glReleaseShaderCompiler();
+}
+
+void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glRenderbufferStorageEXT(target, internalformat, width, height);
+}
+
+void GraphicsContext3D::sampleCoverage(double value, bool invert)
+{
+ ensureContext(m_contextObj);
+ ::glSampleCoverage(static_cast<float>(value), invert);
+}
+
+void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glScissor(x, y, width, height);
+}
+
+void GraphicsContext3D::shaderSource(CanvasShader* shader, const String& string)
+{
+ if (!shader)
+ return;
+
+ ensureContext(m_contextObj);
+ const CString& cs = string.utf8();
+ const char* s = cs.data();
+
+ int length = string.length();
+ ::glShaderSource((GLuint) shader->object(), 1, &s, &length);
+}
+
+void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilFunc(func, ref, mask);
+}
+
+void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilFuncSeparate(face, func, ref, mask);
+}
+
+void GraphicsContext3D::stencilMask(unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilMask(mask);
+}
+
+void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilMaskSeparate(face, mask);
+}
+
+void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ ensureContext(m_contextObj);
+ ::glStencilOp(fail, zfail, zpass);
+}
+
+void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ ensureContext(m_contextObj);
+ ::glStencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void GraphicsContext3D::texParameterf(unsigned target, unsigned pname, float value)
+{
+ ensureContext(m_contextObj);
+ ::glTexParameterf(target, pname, static_cast<float>(value));
+}
+
+void GraphicsContext3D::texParameteri(unsigned target, unsigned pname, int value)
+{
+ ensureContext(m_contextObj);
+ ::glTexParameteri(target, pname, static_cast<float>(value));
+}
+
+void GraphicsContext3D::uniform1f(long location, float v0)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1f(location, v0);
+}
+
+void GraphicsContext3D::uniform1fv(long location, float* array, int size)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2f(long location, float v0, float v1)
+{
+ ensureContext(m_contextObj);
+ ::glUniform2f(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 2
+ ensureContext(m_contextObj);
+ ::glUniform2fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2)
+{
+ ensureContext(m_contextObj);
+ ::glUniform3f(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 3
+ ensureContext(m_contextObj);
+ ::glUniform3fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3)
+{
+ ensureContext(m_contextObj);
+ ::glUniform4f(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniform4fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform1i(long location, int v0)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1i(location, v0);
+}
+
+void GraphicsContext3D::uniform1iv(long location, int* array, int size)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2i(long location, int v0, int v1)
+{
+ ensureContext(m_contextObj);
+ ::glUniform2i(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 2
+ ensureContext(m_contextObj);
+ ::glUniform2iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2)
+{
+ ensureContext(m_contextObj);
+ ::glUniform3i(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 3
+ ensureContext(m_contextObj);
+ ::glUniform3iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3)
+{
+ ensureContext(m_contextObj);
+ ::glUniform4i(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniform4iv(location, size, array);
+}
+
+void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniformMatrix2fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 9
+ ensureContext(m_contextObj);
+ ::glUniformMatrix3fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 16
+ ensureContext(m_contextObj);
+ ::glUniformMatrix4fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::useProgram(CanvasProgram* program)
+{
+ if (!program)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glUseProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::validateProgram(CanvasProgram* program)
+{
+ if (!program)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glValidateProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib1f(indx, v0);
+}
+
+void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib1fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib2f(indx, v0, v1);
+}
+
+void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib2fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib3f(indx, v0, v1, v2);
+}
+
+void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib3fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib4f(indx, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib4fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttribPointer(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)
+{
+ ensureContext(m_contextObj);
+ ::glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+}
+
+static int sizeForGetParam(unsigned long pname)
+{
+ switch(pname) {
+ case GL_ACTIVE_TEXTURE: return 1;
+ case GL_ALIASED_LINE_WIDTH_RANGE: return 2;
+ case GL_ALIASED_POINT_SIZE_RANGE: return 2;
+ case GL_ALPHA_BITS: return 1;
+ case GL_ARRAY_BUFFER_BINDING: return 1; // (* actually a CanvasBuffer*)
+ case GL_BLEND: return 1;
+ case GL_BLEND_COLOR: return 4;
+ case GL_BLEND_DST_ALPHA: return 1;
+ case GL_BLEND_DST_RGB: return 1;
+ case GL_BLEND_EQUATION_ALPHA: return 1;
+ case GL_BLEND_EQUATION_RGB: return 1;
+ case GL_BLEND_SRC_ALPHA: return 1;
+ case GL_BLEND_SRC_RGB: return 1;
+ case GL_BLUE_BITS: return 1;
+ case GL_COLOR_CLEAR_VALUE: return 4;
+ case GL_COLOR_WRITEMASK: return 4;
+ case GL_COMPRESSED_TEXTURE_FORMATS: return GL_NUM_COMPRESSED_TEXTURE_FORMATS;
+ case GL_CULL_FACE: return 1;
+ case GL_CULL_FACE_MODE: return 1;
+ case GL_CURRENT_PROGRAM: return 1; // (* actually a CanvasProgram*)
+ case GL_DEPTH_BITS: return 1;
+ case GL_DEPTH_CLEAR_VALUE: return 1;
+ case GL_DEPTH_FUNC: return 1;
+ case GL_DEPTH_RANGE: return 2;
+ case GL_DEPTH_TEST: return 1;
+ case GL_DEPTH_WRITEMASK: return 1;
+ case GL_DITHER: return 1;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING: return 1; // (* actually a CanvasBuffer*)
+ case GL_FRAMEBUFFER_BINDING_EXT: return 1; // (* actually a CanvasFramebuffer*)
+ case GL_FRONT_FACE: return 1;
+ case GL_GENERATE_MIPMAP_HINT: return 1;
+ case GL_GREEN_BITS: return 1;
+ //case GL_IMPLEMENTATION_COLOR_READ_FORMAT:return 1;
+ //case GL_IMPLEMENTATION_COLOR_READ_TYPE: return 1;
+ case GL_LINE_WIDTH: return 1;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:return 1;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE: return 1;
+ //case GL_MAX_FRAGMENT_UNIFORM_VECTORS: return 1;
+ case GL_MAX_RENDERBUFFER_SIZE_EXT: return 1;
+ case GL_MAX_TEXTURE_IMAGE_UNITS: return 1;
+ case GL_MAX_TEXTURE_SIZE: return 1;
+ //case GL_MAX_VARYING_VECTORS: return 1;
+ case GL_MAX_VERTEX_ATTRIBS: return 1;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: return 1;
+ //case GL_MAX_VERTEX_UNIFORM_VECTORS: return 1;
+ case GL_MAX_VIEWPORT_DIMS: return 2;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS: return 1;
+ //case GL_NUM_SHADER_BINARY_FORMATS: return 1;
+ case GL_PACK_ALIGNMENT: return 1;
+ case GL_POLYGON_OFFSET_FACTOR: return 1;
+ case GL_POLYGON_OFFSET_FILL: return 1;
+ case GL_POLYGON_OFFSET_UNITS: return 1;
+ case GL_RED_BITS: return 1;
+ case GL_RENDERBUFFER_BINDING_EXT: return 1; // (* actually a CanvasRenderbuffer*)
+ case GL_SAMPLE_BUFFERS: return 1;
+ case GL_SAMPLE_COVERAGE_INVERT: return 1;
+ case GL_SAMPLE_COVERAGE_VALUE: return 1;
+ case GL_SAMPLES: return 1;
+ case GL_SCISSOR_BOX: return 4;
+ case GL_SCISSOR_TEST: return 1;
+ //case GL_SHADER_BINARY_FORMATS: return GL_NUM_SHADER_BINARY_FORMATS;
+ //case GL_SHADER_COMPILER: return 1;
+ case GL_STENCIL_BACK_FAIL: return 1;
+ case GL_STENCIL_BACK_FUNC: return 1;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL: return 1;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS: return 1;
+ case GL_STENCIL_BACK_REF: return 1;
+ case GL_STENCIL_BACK_VALUE_MASK: return 1;
+ case GL_STENCIL_BACK_WRITEMASK: return 1;
+ case GL_STENCIL_BITS: return 1;
+ case GL_STENCIL_CLEAR_VALUE: return 1;
+ case GL_STENCIL_FAIL: return 1;
+ case GL_STENCIL_FUNC: return 1;
+ case GL_STENCIL_PASS_DEPTH_FAIL: return 1;
+ case GL_STENCIL_PASS_DEPTH_PASS: return 1;
+ case GL_STENCIL_REF: return 1;
+ case GL_STENCIL_TEST: return 1;
+ case GL_STENCIL_VALUE_MASK: return 1;
+ case GL_STENCIL_WRITEMASK: return 1;
+ case GL_SUBPIXEL_BITS: return 1;
+ case GL_TEXTURE_BINDING_2D: return 1; // (* actually a CanvasTexture*)
+ case GL_TEXTURE_BINDING_CUBE_MAP: return 1; // (* actually a CanvasTexture*)
+ case GL_UNPACK_ALIGNMENT: return 1;
+ case GL_VIEWPORT: return 4;
+ }
+
+ return -1;
+}
+
+bool GraphicsContext3D::getBoolean(unsigned long pname)
+{
+ int size = sizeForGetParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ bool isAlloced = false;
+ GLboolean buf[4];
+ GLboolean* pbuf = buf;
+
+ if (size > 4) {
+ pbuf = (GLboolean*) malloc(size * sizeof(GLboolean));
+ isAlloced = true;
+ }
+
+ ::glGetBooleanv(pname, pbuf);
+
+ bool value = pbuf[0];
+
+ if (isAlloced)
+ free(pbuf);
+
+ return value;
+}
+
+PassRefPtr<CanvasUnsignedByteArray> GraphicsContext3D::getBooleanv(unsigned long pname)
+{
+ int size = sizeForGetParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ RefPtr<CanvasUnsignedByteArray> array = CanvasUnsignedByteArray::create(size);
+ bool isAlloced = false;
+ GLboolean buf[4];
+ GLboolean* pbuf = buf;
+
+ if (size > 4) {
+ pbuf = (GLboolean*) malloc(size * sizeof(GLboolean));
+ isAlloced = true;
+ }
+
+ ::glGetBooleanv(pname, pbuf);
+
+ for (int i = 0; i < size; ++i)
+ array->set(i, static_cast<unsigned char>(pbuf[i]));
+
+ if (isAlloced)
+ free(pbuf);
+
+ return array;
+}
+
+float GraphicsContext3D::getFloat(unsigned long pname)
+{
+ int size = sizeForGetParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ bool isAlloced = false;
+ GLfloat buf[4];
+ GLfloat* pbuf = buf;
+
+ if (size > 4) {
+ pbuf = (GLfloat*) malloc(size * sizeof(GLfloat));
+ isAlloced = true;
+ }
+
+ ::glGetFloatv(pname, pbuf);
+
+ float value = pbuf[0];
+
+ if (isAlloced)
+ free(pbuf);
+
+ return value;
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getFloatv(unsigned long pname)
+{
+ int size = sizeForGetParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(size);
+ bool isAlloced = false;
+ GLfloat buf[4];
+ GLfloat* pbuf = buf;
+
+ if (size > 4) {
+ pbuf = (GLfloat*) malloc(size * sizeof(GLfloat));
+ isAlloced = true;
+ }
+
+ ::glGetFloatv(pname, pbuf);
+
+ for (int i = 0; i < size; ++i)
+ array->set(i, static_cast<float>(pbuf[i]));
+
+ if (isAlloced)
+ free(pbuf);
+
+ return array;
+}
+
+int GraphicsContext3D::getInteger(unsigned long pname)
+{
+ int size = sizeForGetParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ bool isAlloced = false;
+ GLint buf[4];
+ GLint* pbuf = buf;
+
+ if (size > 4) {
+ pbuf = (GLint*) malloc(size * sizeof(GLint));
+ isAlloced = true;
+ }
+
+ ::glGetIntegerv(pname, pbuf);
+
+ int value = pbuf[0];
+
+ if (isAlloced)
+ free(pbuf);
+
+ return value;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getIntegerv(unsigned long pname)
+{
+ int size = sizeForGetParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(size);
+ bool isAlloced = false;
+ GLint buf[4];
+ GLint* pbuf = buf;
+
+ if (size > 4) {
+ pbuf = (GLint*) malloc(size * sizeof(GLint));
+ isAlloced = true;
+ }
+
+ ::glGetIntegerv(pname, pbuf);
+
+ for (int i = 0; i < size; ++i)
+ array->set(i, static_cast<int>(pbuf[i]));
+
+ if (isAlloced)
+ free(pbuf);
+
+ return array;
+}
+
+int GraphicsContext3D::getBufferParameteri(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getFramebufferAttachmentParameteri(unsigned long target, unsigned long attachment, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getProgrami(CanvasProgram* program, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetProgramiv((GLuint) program->object(), pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getProgramiv(CanvasProgram* program, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetProgramiv((GLuint) program->object(), pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+String GraphicsContext3D::getProgramInfoLog(CanvasProgram* program)
+{
+ if (!program)
+ return String();
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetProgramiv((GLuint) program->object(), GL_INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) malloc(length);
+ ::glGetProgramInfoLog((GLuint) program->object(), length, &size, info);
+ String s(info);
+ free(info);
+ return s;
+}
+
+int GraphicsContext3D::getRenderbufferParameteri(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getShaderi(CanvasShader* shader, unsigned long pname)
+{
+ if (!shader)
+ return 0;
+
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetShaderiv((GLuint) shader->object(), pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getShaderiv(CanvasShader* shader, unsigned long pname)
+{
+ if (!shader)
+ return 0;
+
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetShaderiv((GLuint) shader->object(), pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+String GraphicsContext3D::getShaderInfoLog(CanvasShader* shader)
+{
+ if (!shader)
+ return String();
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetShaderiv((GLuint) shader->object(), GL_INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) malloc(length);
+ ::glGetShaderInfoLog((GLuint) shader->object(), length, &size, info);
+ String s(info);
+ free(info);
+ return s;
+}
+
+String GraphicsContext3D::getShaderSource(CanvasShader* shader)
+{
+ if (!shader)
+ return String();
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetShaderiv((GLuint) shader->object(), GL_SHADER_SOURCE_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) malloc(length);
+ ::glGetShaderSource((GLuint) shader->object(), length, &size, info);
+ String s(info);
+ free(info);
+ return s;
+}
+
+
+float GraphicsContext3D::getTexParameterf(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLfloat data;
+ ::glGetTexParameterfv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(1);
+ GLfloat data;
+ ::glGetTexParameterfv(target, pname, &data);
+ array->set(0, static_cast<float>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getTexParameteri(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetTexParameteriv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetTexParameteriv(target, pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+float GraphicsContext3D::getUniformf(CanvasProgram* program, long location)
+{
+ // FIXME: We need to query glGetUniformLocation to determine the size needed
+ UNUSED_PARAM(program);
+ UNUSED_PARAM(location);
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getUniformfv(CanvasProgram* program, long location)
+{
+ // FIXME: We need to query glGetUniformLocation to determine the size needed
+ UNUSED_PARAM(program);
+ UNUSED_PARAM(location);
+ notImplemented();
+ return 0;
+}
+
+int GraphicsContext3D::getUniformi(CanvasProgram* program, long location)
+{
+ // FIXME: We need to query glGetUniformLocation to determine the size needed
+ UNUSED_PARAM(program);
+ UNUSED_PARAM(location);
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getUniformiv(CanvasProgram* program, long location)
+{
+ // FIXME: We need to query glGetUniformLocation to determine the size needed
+ UNUSED_PARAM(program);
+ UNUSED_PARAM(location);
+ notImplemented();
+ return 0;
+}
+
+long GraphicsContext3D::getUniformLocation(CanvasProgram* program, const String& name)
+{
+ if (!program)
+ return -1;
+
+ ensureContext(m_contextObj);
+ return ::glGetUniformLocation((GLuint) program->object(), name.utf8().data());
+}
+
+static int sizeForGetVertexAttribParam(unsigned long pname)
+{
+ switch(pname) {
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: return 1; // (* actually a CanvasBuffer*)
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED: return 1;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE: return 1;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE: return 1;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE: return 1;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: return 1;
+ case GL_CURRENT_VERTEX_ATTRIB: return 4;
+ }
+
+ return -1;
+}
+
+float GraphicsContext3D::getVertexAttribf(unsigned long index, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLfloat buf[4];
+ ::glGetVertexAttribfv(index, pname, buf);
+ return buf[0];
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long pname)
+{
+ int size = sizeForGetVertexAttribParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(size);
+ GLfloat buf[4];
+ ::glGetVertexAttribfv(index, pname, buf);
+
+ for (int i = 0; i < size; ++i)
+ array->set(i, static_cast<float>(buf[i]));
+
+ return array;
+}
+
+int GraphicsContext3D::getVertexAttribi(unsigned long index, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint buf[4];
+ ::glGetVertexAttribiv(index, pname, buf);
+ return buf[0];
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname)
+{
+ int size = sizeForGetVertexAttribParam(pname);
+ if (size < 1)
+ return 0;
+
+ ensureContext(m_contextObj);
+
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(size);
+ GLint buf[4];
+ ::glGetVertexAttribiv(index, pname, buf);
+
+ for (int i = 0; i < size; ++i)
+ array->set(i, static_cast<int>(buf[i]));
+
+ return array;
+}
+
+long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+
+ void* pointer;
+ ::glGetVertexAttribPointerv(index, pname, &pointer);
+ return reinterpret_cast<long>(pointer);
+}
+
+// Assumes the texture you want to go into is bound
+static void imageToTexture(Image* image, unsigned target, unsigned level)
+{
+ if (!image)
+ return;
+
+ CGImageRef textureImage = image->getCGImageRef();
+ if (!textureImage)
+ return;
+
+ size_t textureWidth = CGImageGetWidth(textureImage);
+ size_t textureHeight = CGImageGetHeight(textureImage);
+
+ GLubyte* textureData = (GLubyte*) malloc(textureWidth * textureHeight * 4);
+ CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth, textureHeight, 8, textureWidth * 4,
+ CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast);
+
+ CGContextDrawImage(textureContext, CGRectMake(0, 0, (CGFloat)textureWidth, (CGFloat)textureHeight), textureImage);
+ CGContextRelease(textureContext);
+
+ ::glTexImage2D(target, level, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
+ free(textureData);
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, CanvasArray* pixels)
+{
+ // FIXME: Need to do bounds checking on the buffer here.
+ ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels->baseAddress());
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, ImageData* pixels)
+{
+ // FIXME: need to implement this form
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(internalformat);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(border);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+
+ if (!image)
+ return -1;
+
+ ensureContext(m_contextObj);
+ CachedImage* cachedImage = image->cachedImage();
+ if (!cachedImage)
+ return -1;
+
+ imageToTexture(cachedImage->image(), target, level);
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+
+ if (!canvas)
+ return -1;
+
+ ensureContext(m_contextObj);
+ ImageBuffer* buffer = canvas->buffer();
+ if (!buffer)
+ return -1;
+
+ imageToTexture(buffer->image(), target, level);
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to implement this form
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(video);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, CanvasArray* pixels)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, ImageData* pixels)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLImageElement* image, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(image);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(canvas);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(video);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+unsigned GraphicsContext3D::createBuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenBuffers(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createFramebuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenFramebuffersEXT(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createProgram()
+{
+ ensureContext(m_contextObj);
+ return glCreateProgram();
+}
+
+unsigned GraphicsContext3D::createRenderbuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenRenderbuffersEXT(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createShader(ShaderType type)
+{
+ ensureContext(m_contextObj);
+ return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
+}
+
+unsigned GraphicsContext3D::createTexture()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenTextures(1, &o);
+ return o;
+}
+
+void GraphicsContext3D::deleteBuffer(unsigned buffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteBuffers(1, &buffer);
+}
+
+void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteFramebuffersEXT(1, &framebuffer);
+}
+
+void GraphicsContext3D::deleteProgram(unsigned program)
+{
+ ensureContext(m_contextObj);
+ glDeleteProgram(program);
+}
+
+void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteRenderbuffersEXT(1, &renderbuffer);
+}
+
+void GraphicsContext3D::deleteShader(unsigned shader)
+{
+ ensureContext(m_contextObj);
+ glDeleteShader(shader);
+}
+
+void GraphicsContext3D::deleteTexture(unsigned texture)
+{
+ ensureContext(m_contextObj);
+ glDeleteTextures(1, &texture);
+}
+
+int GraphicsContext3D::sizeInBytes(int type)
+{
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ default:
+ return 0;
+ }
+}
+
+}
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 2404319..6c9b872 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -50,27 +50,26 @@ void GraphicsContext::drawFocusRing(const Color& color)
int radius = (focusRingWidth() - 1) / 2;
int offset = radius + focusRingOffset();
- CGColorRef colorRef = color.isValid() ? createCGColor(color) : 0;
+ RetainPtr<CGColorRef> colorRef;
+ if (color.isValid())
+ colorRef.adoptCF(createCGColor(color));
- CGMutablePathRef focusRingPath = CGPathCreateMutable();
+ RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
for (unsigned i = 0; i < rectCount; i++)
- CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset));
+ CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
CGContextRef context = platformContext();
#ifdef BUILDING_ON_TIGER
CGContextBeginTransparencyLayer(context, NULL);
#endif
CGContextBeginPath(context);
- CGContextAddPath(context, focusRingPath);
- wkDrawFocusRing(context, colorRef, radius);
+ CGContextAddPath(context, focusRingPath.get());
+ wkDrawFocusRing(context, colorRef.get(), radius);
#ifdef BUILDING_ON_TIGER
CGContextEndTransparencyLayer(context);
#endif
- CGColorRelease(colorRef);
-
- CGPathRelease(focusRingPath);
}
#ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp.
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index ebdc6ac..d0e1108 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -62,6 +62,8 @@ public:
virtual void removeFromParent();
+ virtual void setMaskLayer(GraphicsLayer*);
+
virtual void setPosition(const FloatPoint&);
virtual void setAnchorPoint(const FloatPoint3D&);
virtual void setSize(const FloatSize&);
@@ -86,6 +88,10 @@ public:
virtual void setNeedsDisplay();
virtual void setNeedsDisplayInRect(const FloatRect&);
+#if ENABLE(3D_CANVAS)
+ virtual void setGraphicsContext3DNeedsDisplay();
+#endif
+
virtual void setContentsRect(const IntRect&);
virtual void suspendAnimations(double time);
@@ -98,6 +104,9 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsToVideo(PlatformLayer*);
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
+#endif
virtual PlatformLayer* platformLayer() const;
@@ -170,8 +179,12 @@ private:
void updateContentsImage();
void updateContentsVideo();
+#if ENABLE(3D_CANVAS)
+ void updateContentsGraphicsContext3D();
+#endif
void updateContentsRect();
void updateGeometryOrientation();
+ void updateMaskLayer();
void updateLayerAnimations();
@@ -199,8 +212,12 @@ private:
DirtyRectsChanged = 1 << 16,
ContentsImageChanged = 1 << 17,
ContentsVideoChanged = 1 << 18,
- ContentsRectChanged = 1 << 19,
- GeometryOrientationChanged = 1 << 20
+#if ENABLE(3D_CANVAS)
+ ContentsGraphicsContext3DChanged = 1 << 19,
+#endif
+ ContentsRectChanged = 1 << 20,
+ GeometryOrientationChanged = 1 << 21,
+ MaskLayerChanged = 1 << 22
};
typedef unsigned LayerChangeFlags;
void noteLayerPropertyChanged(LayerChangeFlags flags);
@@ -215,6 +232,9 @@ private:
NoContentsLayer = 0,
ContentsLayerForImage,
ContentsLayerForVideo
+#if ENABLE(3D_CANVAS)
+ ,ContentsLayerForGraphicsLayer3D
+#endif
};
ContentsLayerPurpose m_contentsLayerPurpose;
@@ -260,6 +280,11 @@ private:
Vector<FloatRect> m_dirtyRects;
LayerChangeFlags m_uncommittedChanges;
+
+#if ENABLE(3D_CANVAS)
+ PlatformGraphicsContext3D m_platformGraphicsContext3D;
+ Platform3DObject m_platformTexture;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index e5b9035..e9960f1 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -31,6 +31,9 @@
#import "Animation.h"
#import "BlockExceptions.h"
+#if ENABLE(3D_CANVAS)
+#import "Canvas3DLayer.h"
+#endif
#import "CString.h"
#import "FloatConversion.h"
#import "FloatRect.h"
@@ -145,11 +148,11 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
case TransformOperation::ROTATE_Y:
return [NSNumber numberWithDouble:transformOp ? deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle()) : 0];
case TransformOperation::SCALE_X:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1];
case TransformOperation::SCALE_Y:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1];
case TransformOperation::SCALE_Z:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1];
case TransformOperation::TRANSLATE_X:
return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0];
case TransformOperation::TRANSLATE_Y:
@@ -157,13 +160,23 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
case TransformOperation::TRANSLATE_Z:
return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0];
case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1],
+ nil];
case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0],
+ nil];
case TransformOperation::SKEW_X:
case TransformOperation::SKEW_Y:
case TransformOperation::SKEW:
case TransformOperation::MATRIX:
- case TransformOperation::SCALE_3D:
- case TransformOperation::TRANSLATE_3D:
case TransformOperation::ROTATE_3D:
case TransformOperation::MATRIX_3D:
case TransformOperation::PERSPECTIVE:
@@ -204,6 +217,12 @@ static NSString* getValueFunctionNameForTransformOperation(TransformOperation::O
return @"translateY"; // kCAValueFunctionTranslateY;
case TransformOperation::TRANSLATE_Z:
return @"translateZ"; // kCAValueFunctionTranslateZ;
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return @"scale"; // kCAValueFunctionScale;
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return @"translate"; // kCAValueFunctionTranslate;
default:
return nil;
}
@@ -331,7 +350,7 @@ static NSDictionary* nullActionsDictionary()
return actions;
}
-GraphicsLayer* GraphicsLayer::createGraphicsLayer(GraphicsLayerClient* client)
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
{
return new GraphicsLayerCA(client);
}
@@ -341,6 +360,10 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
, m_contentsLayerPurpose(NoContentsLayer)
, m_contentsLayerHasBackgroundColor(false)
, m_uncommittedChanges(NoChange)
+#if ENABLE(3D_CANVAS)
+, m_platformGraphicsContext3D(NullPlatformGraphicsContext3D)
+, m_platformTexture(NullPlatform3DObject)
+#endif
{
BEGIN_BLOCK_OBJC_EXCEPTIONS
m_layer.adoptNS([[WebLayer alloc] init]);
@@ -432,6 +455,15 @@ void GraphicsLayerCA::removeFromParent()
GraphicsLayer::removeFromParent();
}
+void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+ noteLayerPropertyChanged(MaskLayerChanged);
+}
+
void GraphicsLayerCA::setPosition(const FloatPoint& point)
{
if (point == m_position)
@@ -672,10 +704,10 @@ void GraphicsLayerCA::setContentsToImage(Image* image)
CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
- if (CFEqual(colorSpace, deviceRGB)) {
- // CoreGraphics renders images tagged with DeviceRGB using GenericRGB. When we hand such
+ if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
+ // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
// images to CA we need to tag them similarly so CA rendering matches CG rendering.
- static CGColorSpaceRef genericRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
}
m_contentsLayerPurpose = ContentsLayerForImage;
@@ -733,6 +765,9 @@ void GraphicsLayerCA::recursiveCommitChanges()
{
commitLayerChanges();
+ if (m_maskLayer)
+ static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChanges();
+
const Vector<GraphicsLayer*>& childLayers = children();
size_t numChildren = childLayers.size();
for (size_t i = 0; i < numChildren; ++i) {
@@ -763,7 +798,12 @@ void GraphicsLayerCA::commitLayerChanges()
if (m_uncommittedChanges & ContentsVideoChanged) // Needs to happen before ChildrenChanged
updateContentsVideo();
-
+
+#if ENABLE(3D_CANVAS)
+ if (m_uncommittedChanges & ContentsGraphicsContext3DChanged) // Needs to happen before ChildrenChanged
+ updateContentsGraphicsContext3D();
+#endif
+
if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
updateLayerBackgroundColor();
@@ -812,6 +852,9 @@ void GraphicsLayerCA::commitLayerChanges()
if (m_uncommittedChanges & GeometryOrientationChanged)
updateGeometryOrientation();
+ if (m_uncommittedChanges & MaskLayerChanged)
+ updateMaskLayer();
+
m_uncommittedChanges = NoChange;
END_BLOCK_OBJC_EXCEPTIONS
}
@@ -821,10 +864,12 @@ void GraphicsLayerCA::updateSublayerList()
NSMutableArray* newSublayers = nil;
if (m_transformLayer) {
- // FIXME: add the primary layer in the correct order with negative z-order children.
+ // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
newSublayers = [[NSMutableArray alloc] initWithObjects:m_layer.get(), nil];
} else if (m_contentsLayer) {
// FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
newSublayers = [[NSMutableArray alloc] initWithObjects:m_contentsLayer.get(), nil];
}
@@ -1061,6 +1106,18 @@ void GraphicsLayerCA::updateContentsVideo()
}
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::updateContentsGraphicsContext3D()
+{
+ // Canvas3D layer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ [m_contentsLayer.get() setNeedsDisplay];
+ updateContentsRect();
+ }
+}
+#endif
+
void GraphicsLayerCA::updateContentsRect()
{
if (!m_contentsLayer)
@@ -1094,6 +1151,12 @@ void GraphicsLayerCA::updateGeometryOrientation()
#endif
}
+void GraphicsLayerCA::updateMaskLayer()
+{
+ CALayer* maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
+ [m_layer.get() setMask:maskCALayer];
+}
+
void GraphicsLayerCA::updateLayerAnimations()
{
if (m_transitionPropertiesToRemove.size()) {
@@ -1247,6 +1310,40 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, int ind
[layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation.
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* graphicsContext3D)
+{
+ PlatformGraphicsContext3D context = graphicsContext3D->platformGraphicsContext3D();
+ Platform3DObject texture = graphicsContext3D->platformTexture();
+
+ if (context == m_platformGraphicsContext3D && texture == m_platformTexture)
+ return;
+
+ m_platformGraphicsContext3D = context;
+ m_platformTexture = texture;
+
+ noteLayerPropertyChanged(ChildrenChanged);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+
+ if (m_platformGraphicsContext3D != NullPlatformGraphicsContext3D && m_platformTexture != NullPlatform3DObject) {
+ // create the inner 3d layer
+ m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:static_cast<CGLContextObj>(m_platformGraphicsContext3D) texture:static_cast<GLuint>(m_platformTexture)]);
+#ifndef NDEBUG
+ [m_contentsLayer.get() setName:@"3D Layer"];
+#endif
+ } else {
+ // remove the inner layer
+ m_contentsLayer = 0;
+ }
+
+ END_BLOCK_OBJC_EXCEPTIONS
+
+ noteLayerPropertyChanged(ContentsGraphicsContext3DChanged);
+ m_contentsLayerPurpose = m_contentsLayer ? ContentsLayerForGraphicsLayer3D : NoContentsLayer;
+}
+#endif
+
void GraphicsLayerCA::repaintLayerDirtyRects()
{
if (!m_dirtyRects.size())
@@ -1765,6 +1862,14 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
m_uncommittedChanges |= flags;
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::setGraphicsContext3DNeedsDisplay()
+{
+ if (m_contentsLayerPurpose == ContentsLayerForGraphicsLayer3D)
+ [m_contentsLayer.get() setNeedsDisplay];
+}
+#endif
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm
index a0d257b..672c3c8 100644
--- a/WebCore/platform/graphics/mac/ImageMac.mm
+++ b/WebCore/platform/graphics/mac/ImageMac.mm
@@ -94,16 +94,15 @@ CFDataRef BitmapImage::getTIFFRepresentation()
RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(0, 0));
// FIXME: Use type kCGImageTypeIdentifierTIFF constant once is becomes available in the API
- CGImageDestinationRef destination = CGImageDestinationCreateWithData(data.get(), CFSTR("public.tiff"), numValidFrames, 0);
-
+ RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), CFSTR("public.tiff"), numValidFrames, 0));
+
if (!destination)
return 0;
for (unsigned i = 0; i < numValidFrames; ++i)
- CGImageDestinationAddImage(destination, images[i], 0);
+ CGImageDestinationAddImage(destination.get(), images[i], 0);
- CGImageDestinationFinalize(destination);
- CFRelease(destination);
+ CGImageDestinationFinalize(destination.get());
m_tiffRep = data;
return m_tiffRep.get();
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 54eea00..0a63626 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -77,8 +77,12 @@ private:
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
static bool isAvailable();
+ PlatformMedia platformMedia() const;
+
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
+ bool supportsFullscreen() const;
void load(const String& url);
void cancelLoad();
@@ -104,7 +108,7 @@ private:
MediaPlayer::NetworkState networkState() const { return m_networkState; }
MediaPlayer::ReadyState readyState() const { return m_readyState; }
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index c1d7fcb..30d0c82 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -39,6 +39,7 @@
#import "KURL.h"
#import "MIMETypeRegistry.h"
#import "SoftLinking.h"
+#import "TimeRanges.h"
#import "WebCoreSystemInterface.h"
#import <QTKit/QTKit.h>
#import <objc/objc-runtime.h>
@@ -84,6 +85,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieHasAudioAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
@@ -119,6 +121,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()
#define QTMovieDidEndNotification getQTMovieDidEndNotification()
#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()
+#define QTMovieHasAudioAttribute getQTMovieHasAudioAttribute()
#define QTMovieIsActiveAttribute getQTMovieIsActiveAttribute()
#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
@@ -230,7 +233,7 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
void MediaPlayerPrivate::createQTMovie(const String& url)
{
- NSURL *cocoaURL = KURL(url);
+ NSURL *cocoaURL = KURL(ParsedURLString, url);
NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
cocoaURL, QTMovieURLAttribute,
[NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute,
@@ -562,6 +565,12 @@ void MediaPlayerPrivate::load(const String& url)
[m_objcObserver.get() setDelayCallbacks:NO];
}
+PlatformMedia MediaPlayerPrivate::platformMedia() const
+{
+ PlatformMedia plaftformMedia = { m_qtMovie.get() };
+ return plaftformMedia;
+}
+
void MediaPlayerPrivate::play()
{
if (!metaDataAvailable())
@@ -719,18 +728,28 @@ bool MediaPlayerPrivate::hasVideo() const
return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue];
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ if (!m_qtMovie)
+ return false;
+ return [[m_qtMovie.get() attributeForKey:QTMovieHasAudioAttribute] boolValue];
+}
+
+bool MediaPlayerPrivate::supportsFullscreen() const
+{
+ return true;
+}
+
void MediaPlayerPrivate::setVolume(float volume)
{
- if (!metaDataAvailable())
- return;
- [m_qtMovie.get() setVolume:volume];
+ if (m_qtMovie)
+ [m_qtMovie.get() setVolume:volume];
}
void MediaPlayerPrivate::setRate(float rate)
{
- if (!metaDataAvailable())
- return;
- [m_qtMovie.get() setRate:rate];
+ if (m_qtMovie)
+ [m_qtMovie.get() setRate:rate];
}
void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch)
@@ -758,10 +777,13 @@ int MediaPlayerPrivate::dataRate() const
return wkQTMovieDataRate(m_qtMovie.get());
}
-
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
- return maxTimeLoaded();
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
+ if (loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index cdde7cf..97a7251 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -50,6 +50,8 @@
- (BOOL)_isFakeFixedPitch;
@end
+using namespace std;
+
namespace WebCore {
const float smallCapsFontSizeMultiplier = 0.7f;
@@ -269,7 +271,7 @@ void SimpleFontData::platformInit()
// and web pages that foolishly use this metric for width will be laid out
// poorly if we return an accurate height. Classic case is Times 13 point,
// which has an "x" that is 7x6 pixels.
- m_xHeight = MAX(NSMaxX(xBox), NSMaxY(xBox));
+ m_xHeight = max(NSMaxX(xBox), NSMaxY(xBox));
} else
m_xHeight = [m_platformData.font() xHeight];
}
@@ -443,13 +445,13 @@ CTFontRef SimpleFontData::getCTFont() const
return m_CTFont.get();
}
-CFDictionaryRef SimpleFontData::getCFStringAttributes() const
+CFDictionaryRef SimpleFontData::getCFStringAttributes(TextRenderingMode textMode) const
{
if (m_CFStringAttributes)
return m_CFStringAttributes.get();
- static const float kerningAdjustmentValue = 0;
- static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
+ bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+ bool allowLigatures = platformData().allowsLigatures() || allowKerning;
static const int ligaturesNotAllowedValue = 0;
static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue);
@@ -457,10 +459,23 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes() const
static const int ligaturesAllowedValue = 1;
static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue);
- static const void* attributeKeys[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
- const void* attributeValues[] = { getCTFont(), kerningAdjustment, platformData().allowsLigatures() ? ligaturesAllowed : ligaturesNotAllowed };
-
- m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, attributeKeys, attributeValues, sizeof(attributeKeys) / sizeof(*attributeKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ if (!allowKerning) {
+ static const float kerningAdjustmentValue = 0;
+ static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
+ static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
+ const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures
+ ? ligaturesAllowed : ligaturesNotAllowed };
+ m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled,
+ sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled),
+ &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ } else {
+ // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning.
+ static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName };
+ const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed };
+ m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled,
+ sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled),
+ &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ }
return m_CFStringAttributes.get();
}