diff options
author | Steve Block <steveblock@google.com> | 2009-10-08 17:19:54 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-10-20 00:41:58 +0100 |
commit | 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch) | |
tree | a6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/platform/graphics/mac | |
parent | e196732677050bd463301566a68a643b6d14b907 (diff) | |
download | external_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.h | 50 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/Canvas3DLayer.mm | 123 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/CoreTextController.cpp | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/FontCustomPlatformData.cpp | 12 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/FontMac.mm | 27 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/FontMacATSUI.mm | 47 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp | 1698 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsContextMac.mm | 15 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsLayerCA.h | 29 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/GraphicsLayerCA.mm | 127 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/ImageMac.mm | 9 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h | 6 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm | 42 | ||||
-rw-r--r-- | WebCore/platform/graphics/mac/SimpleFontDataMac.mm | 31 |
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(); } |