Source/WebCore/ChangeLog

 12015-01-13 Roger Fong <roger_fong@apple.com>
 2
 3 WebGL2: Support webgl2 context creation.
 4 https://bugs.webkit.org/show_bug.cgi?id=126408
 5 <rdar://problem/15002170>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Tests covered by existing Khronos tests for WebGL 1.0 conformance.
 10
 11 Create a WebGLRenderingContextBase class that extends to a WebGL1RenderingContext and WebGL2RenderingContext.
 12 Replace all previous instances of WebGLRenderingContext usages with WebGLRenderingContextBase usages for now.
 13 As the first step, the WebGL1 and WebGL2 contexts will have the exact same functionality.
 14
 15 * CMakeLists.txt:
 16 * DerivedSources.make:
 17 * WebCore.xcodeproj/project.pbxproj:
 18 * bindings/js/JSCanvasRenderingContextCustom.cpp:
 19 (WebCore::toJS):
 20 * bindings/js/JSDocumentCustom.cpp:
 21 * bindings/js/JSHTMLCanvasElementCustom.cpp:
 22 * bindings/js/JSWebGL1RenderingContextCustom.cpp: Copied from Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp.
 23 * bindings/js/JSWebGL2RenderingContextCustom.cpp: Added.
 24 (WebCore::JSWebGL2RenderingContext::visitAdditionalChildren):
 25 * bindings/js/JSWebGLRenderingContextBaseCustom.cpp: Added.
 26 * bindings/js/JSWebGLRenderingContextCustom.cpp: Removed.
 27 * bindings/scripts/CodeGeneratorJS.pm:
 28 (GenerateImplementation):
 29 * html/HTMLCanvasElement.cpp:
 30 (WebCore::HTMLCanvasElement::getContext):
 31 (WebCore::HTMLCanvasElement::is3dType):
 32 (WebCore::HTMLCanvasElement::reset):
 33 (WebCore::HTMLCanvasElement::paint):
 34 (WebCore::HTMLCanvasElement::getImageData):
 35 * html/canvas/ANGLEInstancedArrays.cpp:
 36 (WebCore::ANGLEInstancedArrays::ANGLEInstancedArrays):
 37 (WebCore::ANGLEInstancedArrays::supported):
 38 * html/canvas/ANGLEInstancedArrays.h:
 39 * html/canvas/CanvasRenderingContext.h:
 40 (WebCore::CanvasRenderingContext::type):
 41 * html/canvas/CanvasRenderingContext2D.cpp:
 42 (WebCore::CanvasRenderingContext2D::CanvasRenderingContext2D):
 43 * html/canvas/EXTBlendMinMax.cpp:
 44 (WebCore::EXTBlendMinMax::EXTBlendMinMax):
 45 * html/canvas/EXTBlendMinMax.h:
 46 * html/canvas/EXTFragDepth.cpp:
 47 (WebCore::EXTFragDepth::EXTFragDepth):
 48 * html/canvas/EXTFragDepth.h:
 49 * html/canvas/EXTShaderTextureLOD.cpp:
 50 (WebCore::EXTShaderTextureLOD::EXTShaderTextureLOD):
 51 * html/canvas/EXTShaderTextureLOD.h:
 52 * html/canvas/EXTTextureFilterAnisotropic.cpp:
 53 (WebCore::EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic):
 54 * html/canvas/EXTTextureFilterAnisotropic.h:
 55 * html/canvas/EXTsRGB.cpp:
 56 (WebCore::EXTsRGB::EXTsRGB):
 57 * html/canvas/EXTsRGB.h:
 58 * html/canvas/OESElementIndexUint.cpp:
 59 (WebCore::OESElementIndexUint::OESElementIndexUint):
 60 * html/canvas/OESElementIndexUint.h:
 61 * html/canvas/OESStandardDerivatives.cpp:
 62 (WebCore::OESStandardDerivatives::OESStandardDerivatives):
 63 * html/canvas/OESStandardDerivatives.h:
 64 * html/canvas/OESTextureFloat.cpp:
 65 (WebCore::OESTextureFloat::OESTextureFloat):
 66 * html/canvas/OESTextureFloat.h:
 67 * html/canvas/OESTextureFloatLinear.cpp:
 68 (WebCore::OESTextureFloatLinear::OESTextureFloatLinear):
 69 * html/canvas/OESTextureFloatLinear.h:
 70 * html/canvas/OESTextureHalfFloat.cpp:
 71 (WebCore::OESTextureHalfFloat::OESTextureHalfFloat):
 72 * html/canvas/OESTextureHalfFloat.h:
 73 * html/canvas/OESTextureHalfFloatLinear.cpp:
 74 (WebCore::OESTextureHalfFloatLinear::OESTextureHalfFloatLinear):
 75 * html/canvas/OESTextureHalfFloatLinear.h:
 76 * html/canvas/OESVertexArrayObject.cpp:
 77 (WebCore::OESVertexArrayObject::OESVertexArrayObject):
 78 * html/canvas/OESVertexArrayObject.h:
 79 * html/canvas/WebGL1RenderingContext.cpp: Copied from Source/WebCore/html/canvas/WebGLRenderingContext.cpp.
 80 * html/canvas/WebGL1RenderingContext.h: Copied from Source/WebCore/html/canvas/WebGLRenderingContext.h.
 81 * html/canvas/WebGL1RenderingContext.idl: Copied from Source/WebCore/html/canvas/WebGLRenderingContext.idl.
 82 * html/canvas/WebGL2RenderingContext.cpp: Added.
 83 (WebCore::WebGL2RenderingContext::WebGL2RenderingContext):
 84 * html/canvas/WebGL2RenderingContext.h: Added.
 85 * html/canvas/WebGL2RenderingContext.idl: Added.
 86 * html/canvas/WebGLBuffer.cpp:
 87 (WebCore::WebGLBuffer::create):
 88 (WebCore::WebGLBuffer::WebGLBuffer):
 89 * html/canvas/WebGLBuffer.h:
 90 * html/canvas/WebGLCompressedTextureATC.cpp:
 91 (WebCore::WebGLCompressedTextureATC::WebGLCompressedTextureATC):
 92 (WebCore::WebGLCompressedTextureATC::supported):
 93 * html/canvas/WebGLCompressedTextureATC.h:
 94 * html/canvas/WebGLCompressedTexturePVRTC.cpp:
 95 (WebCore::WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC):
 96 (WebCore::WebGLCompressedTexturePVRTC::supported):
 97 * html/canvas/WebGLCompressedTexturePVRTC.h:
 98 * html/canvas/WebGLCompressedTextureS3TC.cpp:
 99 (WebCore::WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC):
 100 (WebCore::WebGLCompressedTextureS3TC::supported):
 101 * html/canvas/WebGLCompressedTextureS3TC.h:
 102 * html/canvas/WebGLContextGroup.cpp:
 103 (WebCore::WebGLContextGroup::getAGraphicsContext3D):
 104 (WebCore::WebGLContextGroup::addContext):
 105 (WebCore::WebGLContextGroup::removeContext):
 106 (WebCore::WebGLContextGroup::loseContextGroup):
 107 * html/canvas/WebGLContextGroup.h:
 108 * html/canvas/WebGLContextObject.cpp:
 109 (WebCore::WebGLContextObject::WebGLContextObject):
 110 * html/canvas/WebGLContextObject.h:
 111 (WebCore::WebGLContextObject::context):
 112 * html/canvas/WebGLDebugRendererInfo.cpp:
 113 (WebCore::WebGLDebugRendererInfo::WebGLDebugRendererInfo):
 114 * html/canvas/WebGLDebugRendererInfo.h:
 115 * html/canvas/WebGLDebugShaders.cpp:
 116 (WebCore::WebGLDebugShaders::WebGLDebugShaders):
 117 * html/canvas/WebGLDebugShaders.h:
 118 * html/canvas/WebGLDepthTexture.cpp:
 119 (WebCore::WebGLDepthTexture::WebGLDepthTexture):
 120 * html/canvas/WebGLDepthTexture.h:
 121 * html/canvas/WebGLDrawBuffers.cpp:
 122 (WebCore::WebGLDrawBuffers::WebGLDrawBuffers):
 123 (WebCore::WebGLDrawBuffers::supported):
 124 (WebCore::WebGLDrawBuffers::satisfiesWebGLRequirements):
 125 * html/canvas/WebGLDrawBuffers.h:
 126 * html/canvas/WebGLExtension.cpp:
 127 (WebCore::WebGLExtension::WebGLExtension):
 128 * html/canvas/WebGLExtension.h:
 129 (WebCore::WebGLExtension::context):
 130 * html/canvas/WebGLFramebuffer.cpp:
 131 (WebCore::WebGLFramebuffer::create):
 132 (WebCore::WebGLFramebuffer::WebGLFramebuffer):
 133 * html/canvas/WebGLFramebuffer.h:
 134 * html/canvas/WebGLLoseContext.cpp:
 135 (WebCore::WebGLLoseContext::WebGLLoseContext):
 136 (WebCore::WebGLLoseContext::loseContext):
 137 * html/canvas/WebGLLoseContext.h:
 138 * html/canvas/WebGLObject.cpp:
 139 (WebCore::WebGLObject::WebGLObject):
 140 * html/canvas/WebGLObject.h:
 141 * html/canvas/WebGLProgram.cpp:
 142 (WebCore::WebGLProgram::create):
 143 (WebCore::WebGLProgram::WebGLProgram):
 144 * html/canvas/WebGLProgram.h:
 145 * html/canvas/WebGLRenderbuffer.cpp:
 146 (WebCore::WebGLRenderbuffer::create):
 147 (WebCore::WebGLRenderbuffer::WebGLRenderbuffer):
 148 * html/canvas/WebGLRenderbuffer.h:
 149 * html/canvas/WebGLRenderingContext.cpp: Removed.
 150 * html/canvas/WebGLRenderingContext.h: Removed.
 151 * html/canvas/WebGLRenderingContext.idl: Removed.
 152 * html/canvas/WebGLRenderingContextBase.cpp: Added.
 153 * html/canvas/WebGLRenderingContextBase.h: Added.
 154 * html/canvas/WebGLRenderingContextBase.idl: Added.
 155 * html/canvas/WebGLShader.cpp:
 156 (WebCore::WebGLShader::create):
 157 (WebCore::WebGLShader::WebGLShader):
 158 * html/canvas/WebGLShader.h:
 159 * html/canvas/WebGLSharedObject.cpp:
 160 (WebCore::WebGLSharedObject::WebGLSharedObject):
 161 * html/canvas/WebGLSharedObject.h:
 162 * html/canvas/WebGLTexture.cpp:
 163 (WebCore::WebGLTexture::create):
 164 (WebCore::WebGLTexture::WebGLTexture):
 165 * html/canvas/WebGLTexture.h:
 166 * html/canvas/WebGLVertexArrayObjectOES.cpp:
 167 (WebCore::WebGLVertexArrayObjectOES::create):
 168 (WebCore::WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES):
 169 * html/canvas/WebGLVertexArrayObjectOES.h:
 170
11712015-01-13 Joseph Pecoraro <pecoraro@apple.com>
2172
3173 Web Inspector: Remove unused ResizeImage and DecodeImageData timeline events
178372

Source/WebCore/CMakeLists.txt

@@set(WebCore_NON_SVG_IDL_FILES
540540 html/canvas/OESTextureHalfFloat.idl
541541 html/canvas/OESTextureHalfFloatLinear.idl
542542 html/canvas/OESVertexArrayObject.idl
 543 html/canvas/WebGL1RenderingContext.idl
 544 html/canvas/WebGL2RenderingContext.idl
543545 html/canvas/WebGLActiveInfo.idl
544546 html/canvas/WebGLBuffer.idl
545547 html/canvas/WebGLCompressedTextureATC.idl

@@set(WebCore_NON_SVG_IDL_FILES
555557 html/canvas/WebGLLoseContext.idl
556558 html/canvas/WebGLProgram.idl
557559 html/canvas/WebGLRenderbuffer.idl
558  html/canvas/WebGLRenderingContext.idl
 560 html/canvas/WebGLRenderingContextBase.idl
559561 html/canvas/WebGLShader.idl
560562 html/canvas/WebGLShaderPrecisionFormat.idl
561563 html/canvas/WebGLTexture.idl

@@set(WebCore_SOURCES
11451147 bindings/js/JSTreeWalkerCustom.cpp
11461148 bindings/js/JSVideoTrackCustom.cpp
11471149 bindings/js/JSVideoTrackListCustom.cpp
1148  bindings/js/JSWebGLRenderingContextCustom.cpp
 1150 bindings/js/JSWebGLRenderingContextBaseCustom.cpp
11491151 bindings/js/JSWebKitPointCustom.cpp
11501152 bindings/js/JSWorkerCustom.cpp
11511153 bindings/js/JSWorkerGlobalScopeBase.cpp

@@set(WebCore_SOURCES
16691671 html/canvas/OESTextureHalfFloat.cpp
16701672 html/canvas/OESTextureHalfFloatLinear.cpp
16711673 html/canvas/OESVertexArrayObject.cpp
 1674 html/canvas/WebGL1RenderingContext.cpp
 1675 html/canvas/WebGL2RenderingContext.cpp
16721676 html/canvas/WebGLBuffer.cpp
16731677 html/canvas/WebGLCompressedTextureATC.cpp
16741678 html/canvas/WebGLCompressedTexturePVRTC.cpp

@@set(WebCore_SOURCES
16881692 html/canvas/WebGLObject.cpp
16891693 html/canvas/WebGLProgram.cpp
16901694 html/canvas/WebGLRenderbuffer.cpp
1691  html/canvas/WebGLRenderingContext.cpp
 1695 html/canvas/WebGLRenderingContextBase.cpp
16921696 html/canvas/WebGLShader.cpp
16931697 html/canvas/WebGLShaderPrecisionFormat.cpp
16941698 html/canvas/WebGLSharedObject.cpp

@@if (ENABLE_WEBGL)
27672771 html/canvas/OESTextureHalfFloat.cpp
27682772 html/canvas/OESTextureHalfFloatLinear.cpp
27692773 html/canvas/OESVertexArrayObject.cpp
 2774 html/canvas/WebGL1RenderingContext.cpp
 2775 html/canvas/WebGL2RenderingContext.cpp
27702776 html/canvas/WebGLBuffer.cpp
27712777 html/canvas/WebGLCompressedTextureATC.cpp
27722778 html/canvas/WebGLCompressedTexturePVRTC.cpp

@@if (ENABLE_WEBGL)
27862792 html/canvas/WebGLObject.cpp
27872793 html/canvas/WebGLProgram.cpp
27882794 html/canvas/WebGLRenderbuffer.cpp
2789  html/canvas/WebGLRenderingContext.cpp
 2795 html/canvas/WebGLRenderingContextBase.cpp
27902796 html/canvas/WebGLShader.cpp
27912797 html/canvas/WebGLShaderPrecisionFormat.cpp
27922798 html/canvas/WebGLSharedObject.cpp

@@if (ENABLE_WEBGL)
28082814 html/canvas/OESTextureHalfFloat.idl
28092815 html/canvas/OESTextureHalfFloatLinear.idl
28102816 html/canvas/OESVertexArrayObject.idl
 2817 html/canvas/WebGL1RenderingContext.idl
 2818 html/canvas/WebGL2RenderingContext.idl
28112819 html/canvas/WebGLActiveInfo.idl
28122820 html/canvas/WebGLBuffer.idl
28132821 html/canvas/WebGLCompressedTextureATC.idl

@@if (ENABLE_WEBGL)
28232831 html/canvas/WebGLLoseContext.idl
28242832 html/canvas/WebGLProgram.idl
28252833 html/canvas/WebGLRenderbuffer.idl
2826  html/canvas/WebGLRenderingContext.idl
 2834 html/canvas/WebGLRenderingContextBase.idl
28272835 html/canvas/WebGLShader.idl
28282836 html/canvas/WebGLShaderPrecisionFormat.idl
28292837 html/canvas/WebGLTexture.idl
178372

Source/WebCore/DerivedSources.make

@@NON_SVG_BINDING_IDLS = \
444444 $(WebCore)/html/canvas/WebGLLoseContext.idl \
445445 $(WebCore)/html/canvas/WebGLProgram.idl \
446446 $(WebCore)/html/canvas/WebGLRenderbuffer.idl \
447  $(WebCore)/html/canvas/WebGLRenderingContext.idl \
448447 $(WebCore)/html/canvas/WebGLShader.idl \
449448 $(WebCore)/html/canvas/WebGLShaderPrecisionFormat.idl \
450449 $(WebCore)/html/canvas/WebGLTexture.idl \
451450 $(WebCore)/html/canvas/WebGLUniformLocation.idl \
452451 $(WebCore)/html/canvas/WebGLVertexArrayObjectOES.idl \
 452 $(WebCore)/html/canvas/WebGLRenderingContextBase.idl \
 453 $(WebCore)/html/canvas/WebGL1RenderingContext.idl \
 454 $(WebCore)/html/canvas/WebGL2RenderingContext.idl \
453455 $(WebCore)/html/track/AudioTrack.idl \
454456 $(WebCore)/html/track/AudioTrackList.idl \
455457 $(WebCore)/html/track/DataCue.idl \
178372

Source/WebCore/WebCore.xcodeproj/project.pbxproj

17271727 49C7B9DA1042D32F0009D447 /* WebGLRenderbuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49C7B9BA1042D32F0009D447 /* WebGLRenderbuffer.h */; };
17281728 49C7B9DC1042D32F0009D447 /* CanvasRenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C7B9BC1042D32F0009D447 /* CanvasRenderingContext.cpp */; };
17291729 49C7B9DD1042D32F0009D447 /* CanvasRenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 49C7B9BD1042D32F0009D447 /* CanvasRenderingContext.h */; };
1730  49C7B9DF1042D32F0009D447 /* WebGLRenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C7B9BF1042D32F0009D447 /* WebGLRenderingContext.cpp */; };
1731  49C7B9E01042D32F0009D447 /* WebGLRenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 49C7B9C01042D32F0009D447 /* WebGLRenderingContext.h */; };
 1730 49C7B9DF1042D32F0009D447 /* WebGL1RenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C7B9BF1042D32F0009D447 /* WebGL1RenderingContext.cpp */; };
 1731 49C7B9E01042D32F0009D447 /* WebGL1RenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 49C7B9C01042D32F0009D447 /* WebGL1RenderingContext.h */; };
17321732 49C7B9E21042D32F0009D447 /* WebGLShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C7B9C21042D32F0009D447 /* WebGLShader.cpp */; };
17331733 49C7B9E31042D32F0009D447 /* WebGLShader.h in Headers */ = {isa = PBXBuildFile; fileRef = 49C7B9C31042D32F0009D447 /* WebGLShader.h */; };
17341734 49C7B9E51042D32F0009D447 /* WebGLTexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C7B9C51042D32F0009D447 /* WebGLTexture.cpp */; };

17681768 49EED1431051969400099FAB /* JSCanvasRenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 49EED13D1051969400099FAB /* JSCanvasRenderingContext.h */; };
17691769 49EED1441051969400099FAB /* JSCanvasRenderingContext2D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED13E1051969400099FAB /* JSCanvasRenderingContext2D.cpp */; };
17701770 49EED1451051969400099FAB /* JSCanvasRenderingContext2D.h in Headers */ = {isa = PBXBuildFile; fileRef = 49EED13F1051969400099FAB /* JSCanvasRenderingContext2D.h */; };
1771  49EED1461051969400099FAB /* JSWebGLRenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED1401051969400099FAB /* JSWebGLRenderingContext.cpp */; };
1772  49EED1471051969400099FAB /* JSWebGLRenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 49EED1411051969400099FAB /* JSWebGLRenderingContext.h */; };
 1771 49EED1461051969400099FAB /* JSWebGL1RenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED1401051969400099FAB /* JSWebGL1RenderingContext.cpp */; };
 1772 49EED1471051969400099FAB /* JSWebGL1RenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 49EED1411051969400099FAB /* JSWebGL1RenderingContext.h */; };
17731773 49EED14E1051971A00099FAB /* JSCanvasRenderingContext2DCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED14B1051971900099FAB /* JSCanvasRenderingContext2DCustom.cpp */; };
1774  49EED14F1051971A00099FAB /* JSWebGLRenderingContextCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED14C1051971A00099FAB /* JSWebGLRenderingContextCustom.cpp */; };
 1774 49EED14F1051971A00099FAB /* JSWebGL1RenderingContextCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED14C1051971A00099FAB /* JSWebGL1RenderingContextCustom.cpp */; };
17751775 49EED1501051971A00099FAB /* JSCanvasRenderingContextCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EED14D1051971A00099FAB /* JSCanvasRenderingContextCustom.cpp */; };
17761776 49FC7A501444AF5F00A5D864 /* DisplayRefreshMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49FC7A4F1444AF5F00A5D864 /* DisplayRefreshMonitor.cpp */; };
17771777 49FFBF1D11C8550E006A7118 /* GraphicsContext3DMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49FFBF1C11C8550E006A7118 /* GraphicsContext3DMac.mm */; };

58405840 D359D793129CA3C00006E5D2 /* DOMHTMLDetailsElementInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = D359D790129CA3C00006E5D2 /* DOMHTMLDetailsElementInternal.h */; };
58415841 D359D8BE129CA55C0006E5D2 /* JSHTMLDetailsElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D359D8BC129CA55C0006E5D2 /* JSHTMLDetailsElement.cpp */; };
58425842 D359D8BF129CA55C0006E5D2 /* JSHTMLDetailsElement.h in Headers */ = {isa = PBXBuildFile; fileRef = D359D8BD129CA55C0006E5D2 /* JSHTMLDetailsElement.h */; };
 5843 D39C72D71A5C8B0B00AED89C /* WebGLRenderingContextBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D39C72D51A5C8B0B00AED89C /* WebGLRenderingContextBase.cpp */; };
 5844 D39C72D81A5C8B0B00AED89C /* WebGLRenderingContextBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D39C72D61A5C8B0B00AED89C /* WebGLRenderingContextBase.h */; };
 5845 D39C72DD1A5C8C8E00AED89C /* WebGL2RenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D39C72DB1A5C8C8E00AED89C /* WebGL2RenderingContext.cpp */; };
 5846 D39C72DE1A5C8C8E00AED89C /* WebGL2RenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D39C72DC1A5C8C8E00AED89C /* WebGL2RenderingContext.h */; };
 5847 D39C72E41A5C93AF00AED89C /* JSWebGL2RenderingContextCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D39C72E31A5C93AF00AED89C /* JSWebGL2RenderingContextCustom.cpp */; };
 5848 D39C72E61A5C940B00AED89C /* JSWebGLRenderingContextBaseCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D39C72E51A5C940B00AED89C /* JSWebGLRenderingContextBaseCustom.cpp */; };
58435849 D3A94A38122DABAC00A37BBC /* MediaQueryList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3A94A31122DABAC00A37BBC /* MediaQueryList.cpp */; };
58445850 D3A94A39122DABAC00A37BBC /* MediaQueryList.h in Headers */ = {isa = PBXBuildFile; fileRef = D3A94A32122DABAC00A37BBC /* MediaQueryList.h */; };
58455851 D3A94A3B122DABAC00A37BBC /* MediaQueryListListener.h in Headers */ = {isa = PBXBuildFile; fileRef = D3A94A34122DABAC00A37BBC /* MediaQueryListListener.h */; };

58495855 D3AA10F4123A98AA0092152B /* MediaQueryMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = D3AA10F2123A98AA0092152B /* MediaQueryMatcher.h */; };
58505856 D3D4E972130C7CFE007BA540 /* HTMLSummaryElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3D4E970130C7CFE007BA540 /* HTMLSummaryElement.cpp */; };
58515857 D3D4E973130C7CFE007BA540 /* HTMLSummaryElement.h in Headers */ = {isa = PBXBuildFile; fileRef = D3D4E971130C7CFE007BA540 /* HTMLSummaryElement.h */; };
 5858 D3E14BB51A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3E14BB31A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.cpp */; };
 5859 D3E14BB61A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D3E14BB41A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.h */; };
 5860 D3E14BB91A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3E14BB71A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.cpp */; };
 5861 D3E14BBA1A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D3E14BB81A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.h */; };
58525862 D619A307144E00BE004BC302 /* ChildListMutationScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D619A305144E00BE004BC302 /* ChildListMutationScope.cpp */; };
58535863 D619A308144E00BE004BC302 /* ChildListMutationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = D619A306144E00BE004BC302 /* ChildListMutationScope.h */; };
58545864 D6489D25166FFCF1007C031B /* JSHTMLTemplateElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6489D23166FFCF1007C031B /* JSHTMLTemplateElement.cpp */; };

87968806 49C7B9BC1042D32F0009D447 /* CanvasRenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CanvasRenderingContext.cpp; path = canvas/CanvasRenderingContext.cpp; sourceTree = "<group>"; };
87978807 49C7B9BD1042D32F0009D447 /* CanvasRenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CanvasRenderingContext.h; path = canvas/CanvasRenderingContext.h; sourceTree = "<group>"; };
87988808 49C7B9BE1042D32F0009D447 /* CanvasRenderingContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CanvasRenderingContext.idl; path = canvas/CanvasRenderingContext.idl; sourceTree = "<group>"; };
8799  49C7B9BF1042D32F0009D447 /* WebGLRenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGLRenderingContext.cpp; path = canvas/WebGLRenderingContext.cpp; sourceTree = "<group>"; };
8800  49C7B9C01042D32F0009D447 /* WebGLRenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGLRenderingContext.h; path = canvas/WebGLRenderingContext.h; sourceTree = "<group>"; };
8801  49C7B9C11042D32F0009D447 /* WebGLRenderingContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebGLRenderingContext.idl; path = canvas/WebGLRenderingContext.idl; sourceTree = "<group>"; };
 8809 49C7B9BF1042D32F0009D447 /* WebGL1RenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGL1RenderingContext.cpp; path = canvas/WebGL1RenderingContext.cpp; sourceTree = "<group>"; };
 8810 49C7B9C01042D32F0009D447 /* WebGL1RenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGL1RenderingContext.h; path = canvas/WebGL1RenderingContext.h; sourceTree = "<group>"; };
 8811 49C7B9C11042D32F0009D447 /* WebGL1RenderingContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebGL1RenderingContext.idl; path = canvas/WebGL1RenderingContext.idl; sourceTree = "<group>"; };
88028812 49C7B9C21042D32F0009D447 /* WebGLShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGLShader.cpp; path = canvas/WebGLShader.cpp; sourceTree = "<group>"; };
88038813 49C7B9C31042D32F0009D447 /* WebGLShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGLShader.h; path = canvas/WebGLShader.h; sourceTree = "<group>"; };
88048814 49C7B9C41042D32F0009D447 /* WebGLShader.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebGLShader.idl; path = canvas/WebGLShader.idl; sourceTree = "<group>"; };

88408850 49EED13D1051969400099FAB /* JSCanvasRenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCanvasRenderingContext.h; sourceTree = "<group>"; };
88418851 49EED13E1051969400099FAB /* JSCanvasRenderingContext2D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCanvasRenderingContext2D.cpp; sourceTree = "<group>"; };
88428852 49EED13F1051969400099FAB /* JSCanvasRenderingContext2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCanvasRenderingContext2D.h; sourceTree = "<group>"; };
8843  49EED1401051969400099FAB /* JSWebGLRenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLRenderingContext.cpp; sourceTree = "<group>"; };
8844  49EED1411051969400099FAB /* JSWebGLRenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLRenderingContext.h; sourceTree = "<group>"; };
 8853 49EED1401051969400099FAB /* JSWebGL1RenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGL1RenderingContext.cpp; sourceTree = "<group>"; };
 8854 49EED1411051969400099FAB /* JSWebGL1RenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGL1RenderingContext.h; sourceTree = "<group>"; };
88458855 49EED14B1051971900099FAB /* JSCanvasRenderingContext2DCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCanvasRenderingContext2DCustom.cpp; sourceTree = "<group>"; };
8846  49EED14C1051971A00099FAB /* JSWebGLRenderingContextCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLRenderingContextCustom.cpp; sourceTree = "<group>"; };
 8856 49EED14C1051971A00099FAB /* JSWebGL1RenderingContextCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGL1RenderingContextCustom.cpp; sourceTree = "<group>"; };
88478857 49EED14D1051971A00099FAB /* JSCanvasRenderingContextCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCanvasRenderingContextCustom.cpp; sourceTree = "<group>"; };
88488858 49FC7A4F1444AF5F00A5D864 /* DisplayRefreshMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayRefreshMonitor.cpp; sourceTree = "<group>"; };
88498859 49FFBF1C11C8550E006A7118 /* GraphicsContext3DMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GraphicsContext3DMac.mm; sourceTree = "<group>"; };

1332013330 D359D790129CA3C00006E5D2 /* DOMHTMLDetailsElementInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLDetailsElementInternal.h; sourceTree = "<group>"; };
1332113331 D359D8BC129CA55C0006E5D2 /* JSHTMLDetailsElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLDetailsElement.cpp; sourceTree = "<group>"; };
1332213332 D359D8BD129CA55C0006E5D2 /* JSHTMLDetailsElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLDetailsElement.h; sourceTree = "<group>"; };
 13333 D39C72D51A5C8B0B00AED89C /* WebGLRenderingContextBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGLRenderingContextBase.cpp; path = canvas/WebGLRenderingContextBase.cpp; sourceTree = "<group>"; };
 13334 D39C72D61A5C8B0B00AED89C /* WebGLRenderingContextBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGLRenderingContextBase.h; path = canvas/WebGLRenderingContextBase.h; sourceTree = "<group>"; };
 13335 D39C72DB1A5C8C8E00AED89C /* WebGL2RenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGL2RenderingContext.cpp; path = canvas/WebGL2RenderingContext.cpp; sourceTree = "<group>"; };
 13336 D39C72DC1A5C8C8E00AED89C /* WebGL2RenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGL2RenderingContext.h; path = canvas/WebGL2RenderingContext.h; sourceTree = "<group>"; };
 13337 D39C72E31A5C93AF00AED89C /* JSWebGL2RenderingContextCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGL2RenderingContextCustom.cpp; sourceTree = "<group>"; };
 13338 D39C72E51A5C940B00AED89C /* JSWebGLRenderingContextBaseCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLRenderingContextBaseCustom.cpp; sourceTree = "<group>"; };
1332313339 D3A94A31122DABAC00A37BBC /* MediaQueryList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaQueryList.cpp; sourceTree = "<group>"; };
1332413340 D3A94A32122DABAC00A37BBC /* MediaQueryList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaQueryList.h; sourceTree = "<group>"; };
1332513341 D3A94A33122DABAC00A37BBC /* MediaQueryList.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaQueryList.idl; sourceTree = "<group>"; };

1333113347 D3AA10F2123A98AA0092152B /* MediaQueryMatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaQueryMatcher.h; sourceTree = "<group>"; };
1333213348 D3D4E970130C7CFE007BA540 /* HTMLSummaryElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLSummaryElement.cpp; sourceTree = "<group>"; };
1333313349 D3D4E971130C7CFE007BA540 /* HTMLSummaryElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLSummaryElement.h; sourceTree = "<group>"; };
 13350 D3E14BB31A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGL2RenderingContext.cpp; sourceTree = "<group>"; };
 13351 D3E14BB41A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGL2RenderingContext.h; sourceTree = "<group>"; };
 13352 D3E14BB71A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLRenderingContextBase.cpp; sourceTree = "<group>"; };
 13353 D3E14BB81A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLRenderingContextBase.h; sourceTree = "<group>"; };
 13354 D3E14BBB1A5DE8F50097A6E9 /* WebGL2RenderingContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebGL2RenderingContext.idl; path = canvas/WebGL2RenderingContext.idl; sourceTree = "<group>"; };
 13355 D3E14BBC1A5DE8F50097A6E9 /* WebGLRenderingContextBase.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebGLRenderingContextBase.idl; path = canvas/WebGLRenderingContextBase.idl; sourceTree = "<group>"; };
1333413356 D619A305144E00BE004BC302 /* ChildListMutationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChildListMutationScope.cpp; sourceTree = "<group>"; };
1333513357 D619A306144E00BE004BC302 /* ChildListMutationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildListMutationScope.h; sourceTree = "<group>"; };
1333613358 D6489D23166FFCF1007C031B /* JSHTMLTemplateElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLTemplateElement.cpp; sourceTree = "<group>"; };

1583615858 49C7B9B91042D32F0009D447 /* WebGLRenderbuffer.cpp */,
1583715859 49C7B9BA1042D32F0009D447 /* WebGLRenderbuffer.h */,
1583815860 49C7B9BB1042D32F0009D447 /* WebGLRenderbuffer.idl */,
15839  49C7B9BF1042D32F0009D447 /* WebGLRenderingContext.cpp */,
15840  49C7B9C01042D32F0009D447 /* WebGLRenderingContext.h */,
15841  49C7B9C11042D32F0009D447 /* WebGLRenderingContext.idl */,
 15861 49C7B9BF1042D32F0009D447 /* WebGL1RenderingContext.cpp */,
 15862 49C7B9C01042D32F0009D447 /* WebGL1RenderingContext.h */,
 15863 49C7B9C11042D32F0009D447 /* WebGL1RenderingContext.idl */,
 15864 D39C72DB1A5C8C8E00AED89C /* WebGL2RenderingContext.cpp */,
 15865 D39C72DC1A5C8C8E00AED89C /* WebGL2RenderingContext.h */,
 15866 D3E14BBB1A5DE8F50097A6E9 /* WebGL2RenderingContext.idl */,
 15867 D39C72D51A5C8B0B00AED89C /* WebGLRenderingContextBase.cpp */,
 15868 D39C72D61A5C8B0B00AED89C /* WebGLRenderingContextBase.h */,
 15869 D3E14BBC1A5DE8F50097A6E9 /* WebGLRenderingContextBase.idl */,
1584215870 49C7B9C21042D32F0009D447 /* WebGLShader.cpp */,
1584315871 49C7B9C31042D32F0009D447 /* WebGLShader.h */,
1584415872 49C7B9C41042D32F0009D447 /* WebGLShader.idl */,

1890718935 49C7B9891042D2D30009D447 /* JSWebGLProgram.h */,
1890818936 49C7B98A1042D2D30009D447 /* JSWebGLRenderbuffer.cpp */,
1890918937 49C7B98B1042D2D30009D447 /* JSWebGLRenderbuffer.h */,
18910  49EED1401051969400099FAB /* JSWebGLRenderingContext.cpp */,
18911  49EED1411051969400099FAB /* JSWebGLRenderingContext.h */,
 18938 D3E14BB71A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.cpp */,
 18939 D3E14BB81A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.h */,
 18940 49EED1401051969400099FAB /* JSWebGL1RenderingContext.cpp */,
 18941 49EED1411051969400099FAB /* JSWebGL1RenderingContext.h */,
 18942 D3E14BB31A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.cpp */,
 18943 D3E14BB41A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.h */,
1891218944 49C7B98F1042D2D30009D447 /* JSWebGLShader.cpp */,
1891318945 49C7B9901042D2D30009D447 /* JSWebGLShader.h */,
1891418946 A07D3353152B630E001B6393 /* JSWebGLShaderPrecisionFormat.cpp */,

2100521037 7C73FB17191EF808007DE061 /* JSUserMessageHandlersNamespaceCustom.cpp */,
2100621038 BE6DF708171CA2C500DD52B8 /* JSVideoTrackCustom.cpp */,
2100721039 BE6DF70A171CA2C500DD52B8 /* JSVideoTrackListCustom.cpp */,
21008  49EED14C1051971A00099FAB /* JSWebGLRenderingContextCustom.cpp */,
 21040 D39C72E51A5C940B00AED89C /* JSWebGLRenderingContextBaseCustom.cpp */,
 21041 49EED14C1051971A00099FAB /* JSWebGL1RenderingContextCustom.cpp */,
 21042 D39C72E31A5C93AF00AED89C /* JSWebGL2RenderingContextCustom.cpp */,
2100921043 BC275B7811C5D1C300C9206C /* JSWebKitPointCustom.cpp */,
2101021044 E1CA5CBB0E8CDCAF00E8EF90 /* JSWorkerCustom.cpp */,
2101121045 E18258AB0EF3CD7000933242 /* JSWorkerGlobalScopeCustom.cpp */,

2521825252 93F1D5C112D5335600832BEC /* JSWebGLLoseContext.h in Headers */,
2521925253 49C7B99C1042D2D30009D447 /* JSWebGLProgram.h in Headers */,
2522025254 49C7B99E1042D2D30009D447 /* JSWebGLRenderbuffer.h in Headers */,
25221  49EED1471051969400099FAB /* JSWebGLRenderingContext.h in Headers */,
 25255 49EED1471051969400099FAB /* JSWebGL1RenderingContext.h in Headers */,
2522225256 49C7B9A31042D2D30009D447 /* JSWebGLShader.h in Headers */,
2522325257 A07D3356152B630E001B6393 /* JSWebGLShaderPrecisionFormat.h in Headers */,
2522425258 49C7B9A51042D2D30009D447 /* JSWebGLTexture.h in Headers */,

2545625490 14115B5209F84B7100CA4FC1 /* Node.h in Headers */,
2545725491 854FE7310A2297BE0058D7AD /* NodeFilter.h in Headers */,
2545825492 854FE7330A2297BE0058D7AD /* NodeFilterCondition.h in Headers */,
 25493 D3E14BB61A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.h in Headers */,
2545925494 854FE7350A2297BE0058D7AD /* NodeIterator.h in Headers */,
2546025495 A818721B0977D3C0005826D9 /* NodeList.h in Headers */,
2546125496 63189AE30E83A33300012E41 /* NodeRareData.h in Headers */,

2568625721 E43A023B17EB370A004CDD25 /* RenderElement.h in Headers */,
2568725722 0F5B7A5510F65D7A00376302 /* RenderEmbeddedObject.h in Headers */,
2568825723 A8EA73C40A1900E300A8EF5F /* RenderFieldset.h in Headers */,
 25724 D3E14BBA1A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.h in Headers */,
2568925725 066C77310AB603FD00238CC4 /* RenderFileUploadControl.h in Headers */,
2569025726 53C8298E13D8D92700DE2DEB /* RenderFlexibleBox.h in Headers */,
2569125727 508CCA4F13CF106B003151F3 /* RenderFlowThread.h in Headers */,

2595625992 AB7170890B3118080017123E /* SearchPopupMenu.h in Headers */,
2595725993 93F1E1EC1A40FDDC00348D13 /* NSPopoverSPI.h in Headers */,
2595825994 976F36EB14686225005E93B4 /* SecurityContext.h in Headers */,
 25995 D39C72D81A5C8B0B00AED89C /* WebGLRenderingContextBase.h in Headers */,
2595925996 BCD0E0FB0E972C3500265DEA /* SecurityOrigin.h in Headers */,
2596025997 BCD0E0FC0E972C3500265DEA /* SecurityOriginHash.h in Headers */,
2596125998 974D2DA5146A535D00D51F8B /* SecurityPolicy.h in Headers */,

2663126668 49C7B9D51042D32F0009D447 /* WebGLObject.h in Headers */,
2663226669 49C7B9D71042D32F0009D447 /* WebGLProgram.h in Headers */,
2663326670 49C7B9DA1042D32F0009D447 /* WebGLRenderbuffer.h in Headers */,
26634  49C7B9E01042D32F0009D447 /* WebGLRenderingContext.h in Headers */,
 26671 49C7B9E01042D32F0009D447 /* WebGL1RenderingContext.h in Headers */,
2663526672 49C7B9E31042D32F0009D447 /* WebGLShader.h in Headers */,
2663626673 A07D3358152B632D001B6393 /* WebGLShaderPrecisionFormat.h in Headers */,
2663726674 01D3CF8714BD0A3000FE9970 /* WebGLSharedObject.h in Headers */,

2670026737 A14832C1187F657A00DA63A6 /* WKTypes.h in Headers */,
2670126738 A14832C3187F65DF00DA63A6 /* WKUtilities.h in Headers */,
2670226739 A14832C4187F663C00DA63A6 /* WKView.h in Headers */,
 26740 D39C72DE1A5C8C8E00AED89C /* WebGL2RenderingContext.h in Headers */,
2670326741 A14832C6187F668F00DA63A6 /* WKViewPrivate.h in Headers */,
2670426742 379919971200DDF400EA041C /* WOFFFileFormat.h in Headers */,
2670526743 2E4346460F546A8200B0F1BA /* Worker.h in Headers */,

2769327731 BC53DA481143134D000D817E /* DOMWrapperWorld.cpp in Sources */,
2769427732 1A1D13810A5325520064BF5F /* DOMXPath.mm in Sources */,
2769527733 85E9E0A20AB3A0C700069CD0 /* DOMXPathExpression.mm in Sources */,
 27734 D39C72D71A5C8B0B00AED89C /* WebGLRenderingContextBase.cpp in Sources */,
2769627735 85E9E0A60AB3A0C700069CD0 /* DOMXPathResult.mm in Sources */,
2769727736 FD1762E3176686EA00D836A8 /* DownSampler.cpp in Sources */,
2769827737 A7CA595E0B27BD9E00FA021D /* DragController.cpp in Sources */,

2874328782 267726041A5DF6F2003C24DD /* URLFilterParser.cpp in Sources */,
2874428783 0FDA7C16188322EB00C954B5 /* JSTouch.cpp in Sources */,
2874528784 0FDA7C18188322EB00C954B5 /* JSTouchEvent.cpp in Sources */,
 28785 D39C72E61A5C940B00AED89C /* JSWebGLRenderingContextBaseCustom.cpp in Sources */,
2874628786 0FDA7C1A188322EB00C954B5 /* JSTouchList.cpp in Sources */,
2874728787 070334E9145A1F36008D8D45 /* JSTrackCustom.cpp in Sources */,
2874828788 07846342145B151A00A58DF1 /* JSTrackEvent.cpp in Sources */,

2878228822 93F1D5C012D5335600832BEC /* JSWebGLLoseContext.cpp in Sources */,
2878328823 49C7B99B1042D2D30009D447 /* JSWebGLProgram.cpp in Sources */,
2878428824 49C7B99D1042D2D30009D447 /* JSWebGLRenderbuffer.cpp in Sources */,
28785  49EED1461051969400099FAB /* JSWebGLRenderingContext.cpp in Sources */,
28786  49EED14F1051971A00099FAB /* JSWebGLRenderingContextCustom.cpp in Sources */,
 28825 49EED1461051969400099FAB /* JSWebGL1RenderingContext.cpp in Sources */,
 28826 49EED14F1051971A00099FAB /* JSWebGL1RenderingContextCustom.cpp in Sources */,
2878728827 49C7B9A21042D2D30009D447 /* JSWebGLShader.cpp in Sources */,
2878828828 A07D3355152B630E001B6393 /* JSWebGLShaderPrecisionFormat.cpp in Sources */,
2878928829 49C7B9A41042D2D30009D447 /* JSWebGLTexture.cpp in Sources */,

2894528985 078E090317D14CEE00420AA1 /* MediaStreamTrackEvent.cpp in Sources */,
2894628986 07FFDE68181AED420072D409 /* MediaStreamTrackPrivate.cpp in Sources */,
2894728987 076306D217E1478D005A7C4E /* MediaStreamTrackSourcesRequest.cpp in Sources */,
 28988 D3E14BB51A5DCF4B0097A6E9 /* JSWebGL2RenderingContext.cpp in Sources */,
2894828989 CD641EBF1819B36000EE4C41 /* MediaTimeAVFoundation.cpp in Sources */,
2894928990 CD60C0C6193E87C7003C656B /* MediaTimeQTKit.mm in Sources */,
2895028991 0705853A17FE0770005F2BCB /* MediaTrackConstraint.cpp in Sources */,

2943929480 4B6FA6F70C39E4A100087011 /* SmartReplaceCF.cpp in Sources */,
2944029481 E4AFD00B0DAF335400F5F55C /* SMILTime.cpp in Sources */,
2944129482 E4AFD00D0DAF335500F5F55C /* SMILTimeContainer.cpp in Sources */,
 29483 D39C72E41A5C93AF00AED89C /* JSWebGL2RenderingContextCustom.cpp in Sources */,
2944229484 510D4A33103165EE0049EA54 /* SocketStreamErrorBase.cpp in Sources */,
2944329485 510D4A36103165EE0049EA54 /* SocketStreamHandleBase.cpp in Sources */,
2944429486 51ABAE1F103C1913008C5260 /* SocketStreamHandleCFNet.cpp in Sources */,

2972729769 6550B6A5099DF0270090D781 /* Text.cpp in Sources */,
2972829770 CE7B2DB61586ABAD0098B3FA /* TextAlternativeWithRange.mm in Sources */,
2972929771 0F54DCE51881051D003EEDBB /* TextAutoSizing.cpp in Sources */,
 29772 D3E14BB91A5DCF7B0097A6E9 /* JSWebGLRenderingContextBase.cpp in Sources */,
2973029773 372C00C4129611F1005C9575 /* TextBoundaries.cpp in Sources */,
2973129774 B2AFFC970D00A5DF0030074D /* TextBoundaries.mm in Sources */,
2973229775 BCD8A5F015F56F2C0098D071 /* TextBreakIterator.cpp in Sources */,

2992029963 49C7B9D41042D32F0009D447 /* WebGLObject.cpp in Sources */,
2992129964 49C7B9D61042D32F0009D447 /* WebGLProgram.cpp in Sources */,
2992229965 49C7B9D91042D32F0009D447 /* WebGLRenderbuffer.cpp in Sources */,
29923  49C7B9DF1042D32F0009D447 /* WebGLRenderingContext.cpp in Sources */,
 29966 49C7B9DF1042D32F0009D447 /* WebGL1RenderingContext.cpp in Sources */,
2992429967 49C7B9E21042D32F0009D447 /* WebGLShader.cpp in Sources */,
2992529968 A08CF154152B77B3009C5775 /* WebGLShaderPrecisionFormat.cpp in Sources */,
2992629969 01D3CF8614BD0A3000FE9970 /* WebGLSharedObject.cpp in Sources */,

2997030013 93EC44A1188F4BB800661DF1 /* WheelEventDeltaTracker.cpp in Sources */,
2997130014 9380F47309A11AB4001FDB34 /* Widget.cpp in Sources */,
2997230015 E453904D0EAFD637003695C8 /* WidgetIOS.mm in Sources */,
 30016 D39C72DD1A5C8C8E00AED89C /* WebGL2RenderingContext.cpp in Sources */,
2997330017 9380F47809A11ACC001FDB34 /* WidgetMac.mm in Sources */,
2997430018 939B02EE0EA2DBC400C54570 /* WidthIterator.cpp in Sources */,
2997530019 BC8243E80D0CFD7500460C8F /* WindowFeatures.cpp in Sources */,
178372

Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp

11/*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3232#include "JSNode.h"
3333
3434#if ENABLE(WEBGL)
35 #include "JSWebGLRenderingContext.h"
36 #include "WebGLRenderingContext.h"
 35#include "JSWebGL1RenderingContext.h"
 36#include "JSWebGL2RenderingContext.h"
 37#include "WebGL1RenderingContext.h"
 38#include "WebGL2RenderingContext.h"
3739#endif
3840
3941using namespace JSC;

@@JSC::JSValue toJS(JSC::ExecState*, JSDOM
5153 return jsNull();
5254
5355#if ENABLE(WEBGL)
54  if (object->is3d())
55  return wrap<JSWebGLRenderingContext>(globalObject, static_cast<WebGLRenderingContext*>(object));
 56 if (object->is3d()) {
 57 if (object->type() == "webgl1")
 58 return wrap<JSWebGL1RenderingContext>(globalObject, static_cast<WebGL1RenderingContext*>(object));
 59 if (object->type() == "webgl2")
 60 return wrap<JSWebGL2RenderingContext>(globalObject, static_cast<WebGL2RenderingContext*>(object));
 61 }
5662#endif
5763 ASSERT_WITH_SECURITY_IMPLICATION(object->is2d());
5864 return wrap<JSCanvasRenderingContext2D>(globalObject, static_cast<CanvasRenderingContext2D*>(object));
178372

Source/WebCore/bindings/js/JSDocumentCustom.cpp

3737#include <wtf/GetPtr.h>
3838
3939#if ENABLE(WEBGL)
40 #include "JSWebGLRenderingContext.h"
 40#include "JSWebGLRenderingContextBase.h"
4141#endif
4242
4343#if ENABLE(TOUCH_EVENTS)
178372

Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp

3535
3636#if ENABLE(WEBGL)
3737#include "JSDictionary.h"
38 #include "JSWebGLRenderingContext.h"
 38#include "JSWebGLRenderingContextBase.h"
3939#include "WebGLContextAttributes.h"
4040#endif
4141
178372

Source/WebCore/bindings/js/JSWebGL1RenderingContextCustom.cpp

 1/*
 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEBGL)
 29
 30#include "JSWebGLRenderingContext.h"
 31
 32#include "ANGLEInstancedArrays.h"
 33#include "EXTBlendMinMax.h"
 34#include "EXTFragDepth.h"
 35#include "EXTShaderTextureLOD.h"
 36#include "EXTTextureFilterAnisotropic.h"
 37#include "EXTsRGB.h"
 38#include "ExceptionCode.h"
 39#include "HTMLCanvasElement.h"
 40#include "HTMLImageElement.h"
 41#include "JSANGLEInstancedArrays.h"
 42#include "JSEXTBlendMinMax.h"
 43#include "JSEXTFragDepth.h"
 44#include "JSEXTShaderTextureLOD.h"
 45#include "JSEXTTextureFilterAnisotropic.h"
 46#include "JSEXTsRGB.h"
 47#include "JSHTMLCanvasElement.h"
 48#include "JSHTMLImageElement.h"
 49#include "JSImageData.h"
 50#include "JSOESElementIndexUint.h"
 51#include "JSOESStandardDerivatives.h"
 52#include "JSOESTextureFloat.h"
 53#include "JSOESTextureFloatLinear.h"
 54#include "JSOESTextureHalfFloat.h"
 55#include "JSOESTextureHalfFloatLinear.h"
 56#include "JSOESVertexArrayObject.h"
 57#include "JSWebGLBuffer.h"
 58#include "JSWebGLCompressedTextureATC.h"
 59#include "JSWebGLCompressedTexturePVRTC.h"
 60#include "JSWebGLCompressedTextureS3TC.h"
 61#include "JSWebGLDebugRendererInfo.h"
 62#include "JSWebGLDebugShaders.h"
 63#include "JSWebGLDepthTexture.h"
 64#include "JSWebGLDrawBuffers.h"
 65#include "JSWebGLFramebuffer.h"
 66#include "JSWebGLLoseContext.h"
 67#include "JSWebGLProgram.h"
 68#include "JSWebGLRenderbuffer.h"
 69#include "JSWebGLShader.h"
 70#include "JSWebGLTexture.h"
 71#include "JSWebGLUniformLocation.h"
 72#include "JSWebGLVertexArrayObjectOES.h"
 73#include "JSWebKitCSSMatrix.h"
 74#include "NotImplemented.h"
 75#include "OESElementIndexUint.h"
 76#include "OESStandardDerivatives.h"
 77#include "OESTextureFloat.h"
 78#include "OESTextureFloatLinear.h"
 79#include "OESTextureHalfFloat.h"
 80#include "OESTextureHalfFloatLinear.h"
 81#include "OESVertexArrayObject.h"
 82#include "WebGLBuffer.h"
 83#include "WebGLCompressedTextureATC.h"
 84#include "WebGLCompressedTexturePVRTC.h"
 85#include "WebGLCompressedTextureS3TC.h"
 86#include "WebGLDebugRendererInfo.h"
 87#include "WebGLDebugShaders.h"
 88#include "WebGLDepthTexture.h"
 89#include "WebGLDrawBuffers.h"
 90#include "WebGLExtension.h"
 91#include "WebGLFramebuffer.h"
 92#include "WebGLGetInfo.h"
 93#include "WebGLLoseContext.h"
 94#include "WebGLProgram.h"
 95#include "WebGLRenderingContext.h"
 96#include "WebGLVertexArrayObjectOES.h"
 97#include <runtime/Error.h>
 98#include <runtime/JSTypedArrays.h>
 99#include <runtime/TypedArrayInlines.h>
 100#include <runtime/TypedArrays.h>
 101#include <wtf/FastMalloc.h>
 102
 103#if ENABLE(VIDEO)
 104#include "HTMLVideoElement.h"
 105#include "JSHTMLVideoElement.h"
 106#endif
 107
 108using namespace JSC;
 109
 110namespace WebCore {
 111
 112static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
 113{
 114 switch (info.getType()) {
 115 case WebGLGetInfo::kTypeBool:
 116 return jsBoolean(info.getBool());
 117 case WebGLGetInfo::kTypeBoolArray: {
 118 MarkedArgumentBuffer list;
 119 const Vector<bool>& value = info.getBoolArray();
 120 for (size_t ii = 0; ii < value.size(); ++ii)
 121 list.append(jsBoolean(value[ii]));
 122 return constructArray(exec, 0, globalObject, list);
 123 }
 124 case WebGLGetInfo::kTypeFloat:
 125 return jsNumber(info.getFloat());
 126 case WebGLGetInfo::kTypeInt:
 127 return jsNumber(info.getInt());
 128 case WebGLGetInfo::kTypeNull:
 129 return jsNull();
 130 case WebGLGetInfo::kTypeString:
 131 return jsStringWithCache(exec, info.getString());
 132 case WebGLGetInfo::kTypeUnsignedInt:
 133 return jsNumber(info.getUnsignedInt());
 134 case WebGLGetInfo::kTypeWebGLBuffer:
 135 return toJS(exec, globalObject, info.getWebGLBuffer());
 136 case WebGLGetInfo::kTypeWebGLFloatArray:
 137 return toJS(exec, globalObject, info.getWebGLFloatArray());
 138 case WebGLGetInfo::kTypeWebGLFramebuffer:
 139 return toJS(exec, globalObject, info.getWebGLFramebuffer());
 140 case WebGLGetInfo::kTypeWebGLIntArray:
 141 return toJS(exec, globalObject, info.getWebGLIntArray());
 142 // FIXME: implement WebGLObjectArray
 143 // case WebGLGetInfo::kTypeWebGLObjectArray:
 144 case WebGLGetInfo::kTypeWebGLProgram:
 145 return toJS(exec, globalObject, info.getWebGLProgram());
 146 case WebGLGetInfo::kTypeWebGLRenderbuffer:
 147 return toJS(exec, globalObject, info.getWebGLRenderbuffer());
 148 case WebGLGetInfo::kTypeWebGLTexture:
 149 return toJS(exec, globalObject, info.getWebGLTexture());
 150 case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
 151 return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
 152 case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
 153 return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
 154 case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
 155 return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
 156 default:
 157 notImplemented();
 158 return jsUndefined();
 159 }
 160}
 161
 162enum ObjectType {
 163 kBuffer, kRenderbuffer, kTexture, kVertexAttrib
 164};
 165
 166static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, ObjectType objectType)
 167{
 168 if (exec->argumentCount() != 2)
 169 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 170
 171 ExceptionCode ec = 0;
 172 WebGLRenderingContext& context = obj->impl();
 173 unsigned target = exec->uncheckedArgument(0).toInt32(exec);
 174 if (exec->hadException())
 175 return jsUndefined();
 176 unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
 177 if (exec->hadException())
 178 return jsUndefined();
 179 WebGLGetInfo info;
 180 switch (objectType) {
 181 case kBuffer:
 182 info = context.getBufferParameter(target, pname, ec);
 183 break;
 184 case kRenderbuffer:
 185 info = context.getRenderbufferParameter(target, pname, ec);
 186 break;
 187 case kTexture:
 188 info = context.getTexParameter(target, pname, ec);
 189 break;
 190 case kVertexAttrib:
 191 // target => index
 192 info = context.getVertexAttrib(target, pname, ec);
 193 break;
 194 default:
 195 notImplemented();
 196 break;
 197 }
 198 if (ec) {
 199 setDOMException(exec, ec);
 200 return jsUndefined();
 201 }
 202 return toJS(exec, obj->globalObject(), info);
 203}
 204
 205enum WhichProgramCall {
 206 kProgramParameter, kUniform
 207};
 208
 209static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
 210{
 211 if (!extension)
 212 return jsNull();
 213 switch (extension->getName()) {
 214 case WebGLExtension::WebGLLoseContextName:
 215 return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
 216 case WebGLExtension::EXTShaderTextureLODName:
 217 return toJS(exec, globalObject, static_cast<EXTShaderTextureLOD*>(extension));
 218 case WebGLExtension::EXTTextureFilterAnisotropicName:
 219 return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
 220 case WebGLExtension::EXTsRGBName:
 221 return toJS(exec, globalObject, static_cast<EXTsRGB*>(extension));
 222 case WebGLExtension::EXTFragDepthName:
 223 return toJS(exec, globalObject, static_cast<EXTFragDepth*>(extension));
 224 case WebGLExtension::EXTBlendMinMaxName:
 225 return toJS(exec, globalObject, static_cast<EXTBlendMinMax*>(extension));
 226 case WebGLExtension::OESStandardDerivativesName:
 227 return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
 228 case WebGLExtension::OESTextureFloatName:
 229 return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
 230 case WebGLExtension::OESTextureFloatLinearName:
 231 return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension));
 232 case WebGLExtension::OESTextureHalfFloatName:
 233 return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
 234 case WebGLExtension::OESTextureHalfFloatLinearName:
 235 return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
 236 case WebGLExtension::OESVertexArrayObjectName:
 237 return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
 238 case WebGLExtension::OESElementIndexUintName:
 239 return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
 240 case WebGLExtension::WebGLDebugRendererInfoName:
 241 return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
 242 case WebGLExtension::WebGLDebugShadersName:
 243 return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
 244 case WebGLExtension::WebGLCompressedTextureATCName:
 245 return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
 246 case WebGLExtension::WebGLCompressedTexturePVRTCName:
 247 return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
 248 case WebGLExtension::WebGLCompressedTextureS3TCName:
 249 return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
 250 case WebGLExtension::WebGLDepthTextureName:
 251 return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
 252 case WebGLExtension::WebGLDrawBuffersName:
 253 return toJS(exec, globalObject, static_cast<WebGLDrawBuffers*>(extension));
 254 case WebGLExtension::ANGLEInstancedArraysName:
 255 return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension));
 256 }
 257 ASSERT_NOT_REACHED();
 258 return jsNull();
 259}
 260
 261void JSWebGLRenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
 262{
 263 visitor.addOpaqueRoot(&impl());
 264}
 265
 266JSValue JSWebGLRenderingContext::getAttachedShaders(ExecState* exec)
 267{
 268 if (exec->argumentCount() < 1)
 269 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 270 ExceptionCode ec = 0;
 271 WebGLRenderingContext& context = impl();
 272 WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
 273 if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
 274 return throwTypeError(exec);
 275 Vector<RefPtr<WebGLShader>> shaders;
 276 bool succeed = context.getAttachedShaders(program, shaders, ec);
 277 if (ec) {
 278 setDOMException(exec, ec);
 279 return jsNull();
 280 }
 281 if (!succeed)
 282 return jsNull();
 283 JSC::MarkedArgumentBuffer list;
 284 for (size_t ii = 0; ii < shaders.size(); ++ii)
 285 list.append(toJS(exec, globalObject(), shaders[ii].get()));
 286 return constructArray(exec, 0, globalObject(), list);
 287}
 288
 289JSValue JSWebGLRenderingContext::getExtension(ExecState* exec)
 290{
 291 if (exec->argumentCount() < 1)
 292 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 293
 294 WebGLRenderingContext& context = impl();
 295 const String name = exec->uncheckedArgument(0).toString(exec)->value(exec);
 296 if (exec->hadException())
 297 return jsUndefined();
 298 WebGLExtension* extension = context.getExtension(name);
 299 return toJS(exec, globalObject(), extension);
 300}
 301
 302JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec)
 303{
 304 return getObjectParameter(this, exec, kBuffer);
 305}
 306
 307JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec)
 308{
 309 if (exec->argumentCount() != 3)
 310 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 311
 312 ExceptionCode ec = 0;
 313 WebGLRenderingContext& context = impl();
 314 unsigned target = exec->uncheckedArgument(0).toInt32(exec);
 315 if (exec->hadException())
 316 return jsUndefined();
 317 unsigned attachment = exec->uncheckedArgument(1).toInt32(exec);
 318 if (exec->hadException())
 319 return jsUndefined();
 320 unsigned pname = exec->uncheckedArgument(2).toInt32(exec);
 321 if (exec->hadException())
 322 return jsUndefined();
 323 WebGLGetInfo info = context.getFramebufferAttachmentParameter(target, attachment, pname, ec);
 324 if (ec) {
 325 setDOMException(exec, ec);
 326 return jsUndefined();
 327 }
 328 return toJS(exec, globalObject(), info);
 329}
 330
 331JSValue JSWebGLRenderingContext::getParameter(ExecState* exec)
 332{
 333 if (exec->argumentCount() != 1)
 334 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 335
 336 ExceptionCode ec = 0;
 337 WebGLRenderingContext& context = impl();
 338 unsigned pname = exec->uncheckedArgument(0).toInt32(exec);
 339 if (exec->hadException())
 340 return jsUndefined();
 341 WebGLGetInfo info = context.getParameter(pname, ec);
 342 if (ec) {
 343 setDOMException(exec, ec);
 344 return jsUndefined();
 345 }
 346 return toJS(exec, globalObject(), info);
 347}
 348
 349JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec)
 350{
 351 if (exec->argumentCount() != 2)
 352 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 353
 354 ExceptionCode ec = 0;
 355 WebGLRenderingContext& context = impl();
 356 WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
 357 if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
 358 return throwTypeError(exec);
 359 unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
 360 if (exec->hadException())
 361 return jsUndefined();
 362 WebGLGetInfo info = context.getProgramParameter(program, pname, ec);
 363 if (ec) {
 364 setDOMException(exec, ec);
 365 return jsUndefined();
 366 }
 367 return toJS(exec, globalObject(), info);
 368}
 369
 370JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec)
 371{
 372 return getObjectParameter(this, exec, kRenderbuffer);
 373}
 374
 375JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec)
 376{
 377 if (exec->argumentCount() != 2)
 378 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 379
 380 ExceptionCode ec = 0;
 381 WebGLRenderingContext& context = impl();
 382 if (!exec->uncheckedArgument(0).isUndefinedOrNull() && !exec->uncheckedArgument(0).inherits(JSWebGLShader::info()))
 383 return throwTypeError(exec);
 384 WebGLShader* shader = JSWebGLShader::toWrapped(exec->uncheckedArgument(0));
 385 unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
 386 if (exec->hadException())
 387 return jsUndefined();
 388 WebGLGetInfo info = context.getShaderParameter(shader, pname, ec);
 389 if (ec) {
 390 setDOMException(exec, ec);
 391 return jsUndefined();
 392 }
 393 return toJS(exec, globalObject(), info);
 394}
 395
 396JSValue JSWebGLRenderingContext::getSupportedExtensions(ExecState* exec)
 397{
 398 WebGLRenderingContext& context = impl();
 399 if (context.isContextLost())
 400 return jsNull();
 401 Vector<String> value = context.getSupportedExtensions();
 402 MarkedArgumentBuffer list;
 403 for (size_t ii = 0; ii < value.size(); ++ii)
 404 list.append(jsStringWithCache(exec, value[ii]));
 405 return constructArray(exec, 0, globalObject(), list);
 406}
 407
 408JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec)
 409{
 410 return getObjectParameter(this, exec, kTexture);
 411}
 412
 413JSValue JSWebGLRenderingContext::getUniform(ExecState* exec)
 414{
 415 if (exec->argumentCount() != 2)
 416 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 417
 418 ExceptionCode ec = 0;
 419 WebGLRenderingContext& context = impl();
 420 WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
 421 if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
 422 return throwTypeError(exec);
 423 WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(1));
 424 if (!location && !exec->uncheckedArgument(1).isUndefinedOrNull())
 425 return throwTypeError(exec);
 426 WebGLGetInfo info = context.getUniform(program, location, ec);
 427 if (ec) {
 428 setDOMException(exec, ec);
 429 return jsUndefined();
 430 }
 431 return toJS(exec, globalObject(), info);
 432}
 433
 434JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec)
 435{
 436 return getObjectParameter(this, exec, kVertexAttrib);
 437}
 438
 439template<typename T, size_t inlineCapacity>
 440bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
 441{
 442 if (!value.isObject())
 443 return false;
 444
 445 JSC::JSObject* object = asObject(value);
 446 int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec);
 447
 448 if (!vector.tryReserveCapacity(length))
 449 return false;
 450 vector.resize(length);
 451
 452 for (int32_t i = 0; i < length; ++i) {
 453 JSC::JSValue v = object->get(exec, i);
 454 if (exec->hadException())
 455 return false;
 456 vector[i] = static_cast<T>(v.toNumber(exec));
 457 }
 458
 459 return true;
 460}
 461
 462enum DataFunctionToCall {
 463 f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
 464 f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
 465};
 466
 467enum DataFunctionMatrixToCall {
 468 f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
 469};
 470
 471static bool functionForUniform(DataFunctionToCall f)
 472{
 473 switch (f) {
 474 case f_uniform1v:
 475 case f_uniform2v:
 476 case f_uniform3v:
 477 case f_uniform4v:
 478 return true;
 479 default: break;
 480 }
 481 return false;
 482}
 483
 484static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
 485{
 486 if (exec->argumentCount() != 2)
 487 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 488
 489 WebGLUniformLocation* location = 0;
 490 long index = -1;
 491
 492 if (functionForUniform(f)) {
 493 location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
 494 if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
 495 return throwTypeError(exec);
 496 } else
 497 index = exec->uncheckedArgument(0).toInt32(exec);
 498
 499 if (exec->hadException())
 500 return jsUndefined();
 501
 502 RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1));
 503 if (exec->hadException())
 504 return jsUndefined();
 505
 506 ExceptionCode ec = 0;
 507 if (webGLArray) {
 508 switch (f) {
 509 case f_uniform1v:
 510 context.uniform1fv(location, webGLArray.get(), ec);
 511 break;
 512 case f_uniform2v:
 513 context.uniform2fv(location, webGLArray.get(), ec);
 514 break;
 515 case f_uniform3v:
 516 context.uniform3fv(location, webGLArray.get(), ec);
 517 break;
 518 case f_uniform4v:
 519 context.uniform4fv(location, webGLArray.get(), ec);
 520 break;
 521 case f_vertexAttrib1v:
 522 context.vertexAttrib1fv(index, webGLArray.get());
 523 break;
 524 case f_vertexAttrib2v:
 525 context.vertexAttrib2fv(index, webGLArray.get());
 526 break;
 527 case f_vertexAttrib3v:
 528 context.vertexAttrib3fv(index, webGLArray.get());
 529 break;
 530 case f_vertexAttrib4v:
 531 context.vertexAttrib4fv(index, webGLArray.get());
 532 break;
 533 }
 534
 535 setDOMException(exec, ec);
 536 return jsUndefined();
 537 }
 538
 539 Vector<float, 64> array;
 540 if (!toVector(exec, exec->uncheckedArgument(1), array))
 541 return throwTypeError(exec);
 542
 543 switch (f) {
 544 case f_uniform1v:
 545 context.uniform1fv(location, array.data(), array.size(), ec);
 546 break;
 547 case f_uniform2v:
 548 context.uniform2fv(location, array.data(), array.size(), ec);
 549 break;
 550 case f_uniform3v:
 551 context.uniform3fv(location, array.data(), array.size(), ec);
 552 break;
 553 case f_uniform4v:
 554 context.uniform4fv(location, array.data(), array.size(), ec);
 555 break;
 556 case f_vertexAttrib1v:
 557 context.vertexAttrib1fv(index, array.data(), array.size());
 558 break;
 559 case f_vertexAttrib2v:
 560 context.vertexAttrib2fv(index, array.data(), array.size());
 561 break;
 562 case f_vertexAttrib3v:
 563 context.vertexAttrib3fv(index, array.data(), array.size());
 564 break;
 565 case f_vertexAttrib4v:
 566 context.vertexAttrib4fv(index, array.data(), array.size());
 567 break;
 568 }
 569
 570 setDOMException(exec, ec);
 571 return jsUndefined();
 572}
 573
 574static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
 575{
 576 if (exec->argumentCount() != 2)
 577 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 578
 579 WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
 580 if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
 581 return throwTypeError(exec);
 582
 583 RefPtr<Int32Array> webGLArray = toInt32Array(exec->uncheckedArgument(1));
 584
 585 ExceptionCode ec = 0;
 586 if (webGLArray) {
 587 switch (f) {
 588 case f_uniform1v:
 589 context.uniform1iv(location, webGLArray.get(), ec);
 590 break;
 591 case f_uniform2v:
 592 context.uniform2iv(location, webGLArray.get(), ec);
 593 break;
 594 case f_uniform3v:
 595 context.uniform3iv(location, webGLArray.get(), ec);
 596 break;
 597 case f_uniform4v:
 598 context.uniform4iv(location, webGLArray.get(), ec);
 599 break;
 600 default:
 601 break;
 602 }
 603
 604 setDOMException(exec, ec);
 605 return jsUndefined();
 606 }
 607
 608
 609 Vector<int, 64> array;
 610 if (!toVector(exec, exec->uncheckedArgument(1), array))
 611 return throwTypeError(exec);
 612
 613 switch (f) {
 614 case f_uniform1v:
 615 context.uniform1iv(location, array.data(), array.size(), ec);
 616 break;
 617 case f_uniform2v:
 618 context.uniform2iv(location, array.data(), array.size(), ec);
 619 break;
 620 case f_uniform3v:
 621 context.uniform3iv(location, array.data(), array.size(), ec);
 622 break;
 623 case f_uniform4v:
 624 context.uniform4iv(location, array.data(), array.size(), ec);
 625 break;
 626 default:
 627 break;
 628 }
 629
 630 setDOMException(exec, ec);
 631 return jsUndefined();
 632}
 633
 634static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
 635{
 636 if (exec->argumentCount() != 3)
 637 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 638
 639 WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
 640 if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
 641 return throwTypeError(exec);
 642
 643 bool transpose = exec->uncheckedArgument(1).toBoolean(exec);
 644 if (exec->hadException())
 645 return jsUndefined();
 646
 647 RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(2));
 648
 649 ExceptionCode ec = 0;
 650 if (webGLArray) {
 651 switch (f) {
 652 case f_uniformMatrix2fv:
 653 context.uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
 654 break;
 655 case f_uniformMatrix3fv:
 656 context.uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
 657 break;
 658 case f_uniformMatrix4fv:
 659 context.uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
 660 break;
 661 }
 662
 663 setDOMException(exec, ec);
 664 return jsUndefined();
 665 }
 666
 667 Vector<float, 64> array;
 668 if (!toVector(exec, exec->uncheckedArgument(2), array))
 669 return throwTypeError(exec);
 670
 671 switch (f) {
 672 case f_uniformMatrix2fv:
 673 context.uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
 674 break;
 675 case f_uniformMatrix3fv:
 676 context.uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
 677 break;
 678 case f_uniformMatrix4fv:
 679 context.uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
 680 break;
 681 }
 682
 683 setDOMException(exec, ec);
 684 return jsUndefined();
 685}
 686
 687JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec)
 688{
 689 return dataFunctionf(f_uniform1v, exec, impl());
 690}
 691
 692JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec)
 693{
 694 return dataFunctioni(f_uniform1v, exec, impl());
 695}
 696
 697JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec)
 698{
 699 return dataFunctionf(f_uniform2v, exec, impl());
 700}
 701
 702JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec)
 703{
 704 return dataFunctioni(f_uniform2v, exec, impl());
 705}
 706
 707JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec)
 708{
 709 return dataFunctionf(f_uniform3v, exec, impl());
 710}
 711
 712JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec)
 713{
 714 return dataFunctioni(f_uniform3v, exec, impl());
 715}
 716
 717JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec)
 718{
 719 return dataFunctionf(f_uniform4v, exec, impl());
 720}
 721
 722JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec)
 723{
 724 return dataFunctioni(f_uniform4v, exec, impl());
 725}
 726
 727JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec)
 728{
 729 return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl());
 730}
 731
 732JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec)
 733{
 734 return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl());
 735}
 736
 737JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec)
 738{
 739 return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl());
 740}
 741
 742JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec)
 743{
 744 return dataFunctionf(f_vertexAttrib1v, exec, impl());
 745}
 746
 747JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec)
 748{
 749 return dataFunctionf(f_vertexAttrib2v, exec, impl());
 750}
 751
 752JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec)
 753{
 754 return dataFunctionf(f_vertexAttrib3v, exec, impl());
 755}
 756
 757JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec)
 758{
 759 return dataFunctionf(f_vertexAttrib4v, exec, impl());
 760}
 761
 762} // namespace WebCore
 763
 764#endif // ENABLE(WEBGL)
176994

Source/WebCore/bindings/js/JSWebGL1RenderingContextCustom.cpp

11/*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2626#include "config.h"
2727
2828#if ENABLE(WEBGL)
29 
30 #include "JSWebGLRenderingContext.h"
31 
32 #include "ANGLEInstancedArrays.h"
33 #include "EXTShaderTextureLOD.h"
34 #include "EXTTextureFilterAnisotropic.h"
35 #include "ExceptionCode.h"
36 #include "HTMLCanvasElement.h"
37 #include "HTMLImageElement.h"
38 #include "JSANGLEInstancedArrays.h"
39 #include "JSEXTShaderTextureLOD.h"
40 #include "JSEXTTextureFilterAnisotropic.h"
41 #include "JSHTMLCanvasElement.h"
42 #include "JSHTMLImageElement.h"
43 #include "JSImageData.h"
44 #include "JSOESElementIndexUint.h"
45 #include "JSOESStandardDerivatives.h"
46 #include "JSOESTextureFloat.h"
47 #include "JSOESTextureFloatLinear.h"
48 #include "JSOESTextureHalfFloat.h"
49 #include "JSOESTextureHalfFloatLinear.h"
50 #include "JSOESVertexArrayObject.h"
51 #include "JSWebGLBuffer.h"
52 #include "JSWebGLCompressedTextureATC.h"
53 #include "JSWebGLCompressedTexturePVRTC.h"
54 #include "JSWebGLCompressedTextureS3TC.h"
55 #include "JSWebGLDebugRendererInfo.h"
56 #include "JSWebGLDebugShaders.h"
57 #include "JSWebGLDepthTexture.h"
58 #include "JSWebGLDrawBuffers.h"
59 #include "JSWebGLFramebuffer.h"
60 #include "JSWebGLLoseContext.h"
61 #include "JSWebGLProgram.h"
62 #include "JSWebGLRenderbuffer.h"
63 #include "JSWebGLShader.h"
64 #include "JSWebGLTexture.h"
65 #include "JSWebGLUniformLocation.h"
66 #include "JSWebGLVertexArrayObjectOES.h"
67 #include "JSWebKitCSSMatrix.h"
68 #include "NotImplemented.h"
69 #include "OESElementIndexUint.h"
70 #include "OESStandardDerivatives.h"
71 #include "OESTextureFloat.h"
72 #include "OESTextureFloatLinear.h"
73 #include "OESTextureHalfFloat.h"
74 #include "OESTextureHalfFloatLinear.h"
75 #include "OESVertexArrayObject.h"
76 #include "WebGLBuffer.h"
77 #include "WebGLCompressedTextureATC.h"
78 #include "WebGLCompressedTexturePVRTC.h"
79 #include "WebGLCompressedTextureS3TC.h"
80 #include "WebGLDebugRendererInfo.h"
81 #include "WebGLDebugShaders.h"
82 #include "WebGLDepthTexture.h"
83 #include "WebGLDrawBuffers.h"
84 #include "WebGLExtension.h"
85 #include "WebGLFramebuffer.h"
86 #include "WebGLGetInfo.h"
87 #include "WebGLLoseContext.h"
88 #include "WebGLProgram.h"
89 #include "WebGLRenderingContext.h"
90 #include "WebGLVertexArrayObjectOES.h"
91 #include <runtime/Error.h>
92 #include <runtime/JSTypedArrays.h>
93 #include <runtime/TypedArrayInlines.h>
94 #include <runtime/TypedArrays.h>
95 #include <wtf/FastMalloc.h>
96 
97 #if ENABLE(VIDEO)
98 #include "HTMLVideoElement.h"
99 #include "JSHTMLVideoElement.h"
100 #endif
 29#include "JSWebGL1RenderingContext.h"
10130
10231using namespace JSC;
10332
10433namespace WebCore {
10534
106 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
107 {
108  switch (info.getType()) {
109  case WebGLGetInfo::kTypeBool:
110  return jsBoolean(info.getBool());
111  case WebGLGetInfo::kTypeBoolArray: {
112  MarkedArgumentBuffer list;
113  const Vector<bool>& value = info.getBoolArray();
114  for (size_t ii = 0; ii < value.size(); ++ii)
115  list.append(jsBoolean(value[ii]));
116  return constructArray(exec, 0, globalObject, list);
117  }
118  case WebGLGetInfo::kTypeFloat:
119  return jsNumber(info.getFloat());
120  case WebGLGetInfo::kTypeInt:
121  return jsNumber(info.getInt());
122  case WebGLGetInfo::kTypeNull:
123  return jsNull();
124  case WebGLGetInfo::kTypeString:
125  return jsStringWithCache(exec, info.getString());
126  case WebGLGetInfo::kTypeUnsignedInt:
127  return jsNumber(info.getUnsignedInt());
128  case WebGLGetInfo::kTypeWebGLBuffer:
129  return toJS(exec, globalObject, info.getWebGLBuffer());
130  case WebGLGetInfo::kTypeWebGLFloatArray:
131  return toJS(exec, globalObject, info.getWebGLFloatArray());
132  case WebGLGetInfo::kTypeWebGLFramebuffer:
133  return toJS(exec, globalObject, info.getWebGLFramebuffer());
134  case WebGLGetInfo::kTypeWebGLIntArray:
135  return toJS(exec, globalObject, info.getWebGLIntArray());
136  // FIXME: implement WebGLObjectArray
137  // case WebGLGetInfo::kTypeWebGLObjectArray:
138  case WebGLGetInfo::kTypeWebGLProgram:
139  return toJS(exec, globalObject, info.getWebGLProgram());
140  case WebGLGetInfo::kTypeWebGLRenderbuffer:
141  return toJS(exec, globalObject, info.getWebGLRenderbuffer());
142  case WebGLGetInfo::kTypeWebGLTexture:
143  return toJS(exec, globalObject, info.getWebGLTexture());
144  case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
145  return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
146  case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
147  return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
148  case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
149  return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
150  default:
151  notImplemented();
152  return jsUndefined();
153  }
154 }
155 
156 enum ObjectType {
157  kBuffer, kRenderbuffer, kTexture, kVertexAttrib
158 };
159 
160 static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, ObjectType objectType)
161 {
162  if (exec->argumentCount() != 2)
163  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
164 
165  ExceptionCode ec = 0;
166  WebGLRenderingContext& context = obj->impl();
167  unsigned target = exec->uncheckedArgument(0).toInt32(exec);
168  if (exec->hadException())
169  return jsUndefined();
170  unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
171  if (exec->hadException())
172  return jsUndefined();
173  WebGLGetInfo info;
174  switch (objectType) {
175  case kBuffer:
176  info = context.getBufferParameter(target, pname, ec);
177  break;
178  case kRenderbuffer:
179  info = context.getRenderbufferParameter(target, pname, ec);
180  break;
181  case kTexture:
182  info = context.getTexParameter(target, pname, ec);
183  break;
184  case kVertexAttrib:
185  // target => index
186  info = context.getVertexAttrib(target, pname, ec);
187  break;
188  default:
189  notImplemented();
190  break;
191  }
192  if (ec) {
193  setDOMException(exec, ec);
194  return jsUndefined();
195  }
196  return toJS(exec, obj->globalObject(), info);
197 }
198 
199 enum WhichProgramCall {
200  kProgramParameter, kUniform
201 };
202 
203 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
204 {
205  if (!extension)
206  return jsNull();
207  switch (extension->getName()) {
208  case WebGLExtension::WebGLLoseContextName:
209  return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
210  case WebGLExtension::EXTShaderTextureLODName:
211  return toJS(exec, globalObject, static_cast<EXTShaderTextureLOD*>(extension));
212  case WebGLExtension::EXTTextureFilterAnisotropicName:
213  return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
214  case WebGLExtension::OESStandardDerivativesName:
215  return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
216  case WebGLExtension::OESTextureFloatName:
217  return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
218  case WebGLExtension::OESTextureFloatLinearName:
219  return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension));
220  case WebGLExtension::OESTextureHalfFloatName:
221  return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
222  case WebGLExtension::OESTextureHalfFloatLinearName:
223  return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
224  case WebGLExtension::OESVertexArrayObjectName:
225  return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
226  case WebGLExtension::OESElementIndexUintName:
227  return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
228  case WebGLExtension::WebGLDebugRendererInfoName:
229  return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
230  case WebGLExtension::WebGLDebugShadersName:
231  return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
232  case WebGLExtension::WebGLCompressedTextureATCName:
233  return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
234  case WebGLExtension::WebGLCompressedTexturePVRTCName:
235  return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
236  case WebGLExtension::WebGLCompressedTextureS3TCName:
237  return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
238  case WebGLExtension::WebGLDepthTextureName:
239  return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
240  case WebGLExtension::WebGLDrawBuffersName:
241  return toJS(exec, globalObject, static_cast<WebGLDrawBuffers*>(extension));
242  case WebGLExtension::ANGLEInstancedArraysName:
243  return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension));
244  }
245  ASSERT_NOT_REACHED();
246  return jsNull();
247 }
248 
249 void JSWebGLRenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
 35void JSWebGL1RenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
25036{
25137 visitor.addOpaqueRoot(&impl());
25238}
25339
254 JSValue JSWebGLRenderingContext::getAttachedShaders(ExecState* exec)
255 {
256  if (exec->argumentCount() < 1)
257  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
258  ExceptionCode ec = 0;
259  WebGLRenderingContext& context = impl();
260  WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
261  if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
262  return throwTypeError(exec);
263  Vector<RefPtr<WebGLShader>> shaders;
264  bool succeed = context.getAttachedShaders(program, shaders, ec);
265  if (ec) {
266  setDOMException(exec, ec);
267  return jsNull();
268  }
269  if (!succeed)
270  return jsNull();
271  MarkedArgumentBuffer list;
272  for (size_t ii = 0; ii < shaders.size(); ++ii)
273  list.append(toJS(exec, globalObject(), shaders[ii].get()));
274  return constructArray(exec, 0, globalObject(), list);
275 }
276 
277 JSValue JSWebGLRenderingContext::getExtension(ExecState* exec)
278 {
279  if (exec->argumentCount() < 1)
280  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
281 
282  WebGLRenderingContext& context = impl();
283  const String name = exec->uncheckedArgument(0).toString(exec)->value(exec);
284  if (exec->hadException())
285  return jsUndefined();
286  WebGLExtension* extension = context.getExtension(name);
287  return toJS(exec, globalObject(), extension);
288 }
289 
290 JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec)
291 {
292  return getObjectParameter(this, exec, kBuffer);
293 }
294 
295 JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec)
296 {
297  if (exec->argumentCount() != 3)
298  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
299 
300  ExceptionCode ec = 0;
301  WebGLRenderingContext& context = impl();
302  unsigned target = exec->uncheckedArgument(0).toInt32(exec);
303  if (exec->hadException())
304  return jsUndefined();
305  unsigned attachment = exec->uncheckedArgument(1).toInt32(exec);
306  if (exec->hadException())
307  return jsUndefined();
308  unsigned pname = exec->uncheckedArgument(2).toInt32(exec);
309  if (exec->hadException())
310  return jsUndefined();
311  WebGLGetInfo info = context.getFramebufferAttachmentParameter(target, attachment, pname, ec);
312  if (ec) {
313  setDOMException(exec, ec);
314  return jsUndefined();
315  }
316  return toJS(exec, globalObject(), info);
317 }
318 
319 JSValue JSWebGLRenderingContext::getParameter(ExecState* exec)
320 {
321  if (exec->argumentCount() != 1)
322  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
323 
324  ExceptionCode ec = 0;
325  WebGLRenderingContext& context = impl();
326  unsigned pname = exec->uncheckedArgument(0).toInt32(exec);
327  if (exec->hadException())
328  return jsUndefined();
329  WebGLGetInfo info = context.getParameter(pname, ec);
330  if (ec) {
331  setDOMException(exec, ec);
332  return jsUndefined();
333  }
334  return toJS(exec, globalObject(), info);
335 }
336 
337 JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec)
338 {
339  if (exec->argumentCount() != 2)
340  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
341 
342  ExceptionCode ec = 0;
343  WebGLRenderingContext& context = impl();
344  WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
345  if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
346  return throwTypeError(exec);
347  unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
348  if (exec->hadException())
349  return jsUndefined();
350  WebGLGetInfo info = context.getProgramParameter(program, pname, ec);
351  if (ec) {
352  setDOMException(exec, ec);
353  return jsUndefined();
354  }
355  return toJS(exec, globalObject(), info);
356 }
357 
358 JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec)
359 {
360  return getObjectParameter(this, exec, kRenderbuffer);
361 }
362 
363 JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec)
364 {
365  if (exec->argumentCount() != 2)
366  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
367 
368  ExceptionCode ec = 0;
369  WebGLRenderingContext& context = impl();
370  if (!exec->uncheckedArgument(0).isUndefinedOrNull() && !exec->uncheckedArgument(0).inherits(JSWebGLShader::info()))
371  return throwTypeError(exec);
372  WebGLShader* shader = JSWebGLShader::toWrapped(exec->uncheckedArgument(0));
373  unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
374  if (exec->hadException())
375  return jsUndefined();
376  WebGLGetInfo info = context.getShaderParameter(shader, pname, ec);
377  if (ec) {
378  setDOMException(exec, ec);
379  return jsUndefined();
380  }
381  return toJS(exec, globalObject(), info);
382 }
383 
384 JSValue JSWebGLRenderingContext::getSupportedExtensions(ExecState* exec)
385 {
386  WebGLRenderingContext& context = impl();
387  if (context.isContextLost())
388  return jsNull();
389  Vector<String> value = context.getSupportedExtensions();
390  MarkedArgumentBuffer list;
391  for (size_t ii = 0; ii < value.size(); ++ii)
392  list.append(jsStringWithCache(exec, value[ii]));
393  return constructArray(exec, 0, globalObject(), list);
394 }
395 
396 JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec)
397 {
398  return getObjectParameter(this, exec, kTexture);
399 }
400 
401 JSValue JSWebGLRenderingContext::getUniform(ExecState* exec)
402 {
403  if (exec->argumentCount() != 2)
404  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
405 
406  ExceptionCode ec = 0;
407  WebGLRenderingContext& context = impl();
408  WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
409  if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
410  return throwTypeError(exec);
411  WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(1));
412  if (!location && !exec->uncheckedArgument(1).isUndefinedOrNull())
413  return throwTypeError(exec);
414  WebGLGetInfo info = context.getUniform(program, location, ec);
415  if (ec) {
416  setDOMException(exec, ec);
417  return jsUndefined();
418  }
419  return toJS(exec, globalObject(), info);
420 }
421 
422 JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec)
423 {
424  return getObjectParameter(this, exec, kVertexAttrib);
425 }
426 
427 template<typename T, size_t inlineCapacity>
428 bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
429 {
430  if (!value.isObject())
431  return false;
432 
433  JSC::JSObject* object = asObject(value);
434  int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec);
435 
436  if (!vector.tryReserveCapacity(length))
437  return false;
438  vector.resize(length);
439 
440  for (int32_t i = 0; i < length; ++i) {
441  JSC::JSValue v = object->get(exec, i);
442  if (exec->hadException())
443  return false;
444  vector[i] = static_cast<T>(v.toNumber(exec));
445  }
446 
447  return true;
448 }
449 
450 enum DataFunctionToCall {
451  f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
452  f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
453 };
454 
455 enum DataFunctionMatrixToCall {
456  f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
457 };
458 
459 static bool functionForUniform(DataFunctionToCall f)
460 {
461  switch (f) {
462  case f_uniform1v:
463  case f_uniform2v:
464  case f_uniform3v:
465  case f_uniform4v:
466  return true;
467  default: break;
468  }
469  return false;
470 }
471 
472 static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
473 {
474  if (exec->argumentCount() != 2)
475  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
476 
477  WebGLUniformLocation* location = 0;
478  long index = -1;
479 
480  if (functionForUniform(f)) {
481  location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
482  if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
483  return throwTypeError(exec);
484  } else
485  index = exec->uncheckedArgument(0).toInt32(exec);
486 
487  if (exec->hadException())
488  return jsUndefined();
489 
490  RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1));
491  if (exec->hadException())
492  return jsUndefined();
493 
494  ExceptionCode ec = 0;
495  if (webGLArray) {
496  switch (f) {
497  case f_uniform1v:
498  context.uniform1fv(location, webGLArray.get(), ec);
499  break;
500  case f_uniform2v:
501  context.uniform2fv(location, webGLArray.get(), ec);
502  break;
503  case f_uniform3v:
504  context.uniform3fv(location, webGLArray.get(), ec);
505  break;
506  case f_uniform4v:
507  context.uniform4fv(location, webGLArray.get(), ec);
508  break;
509  case f_vertexAttrib1v:
510  context.vertexAttrib1fv(index, webGLArray.get());
511  break;
512  case f_vertexAttrib2v:
513  context.vertexAttrib2fv(index, webGLArray.get());
514  break;
515  case f_vertexAttrib3v:
516  context.vertexAttrib3fv(index, webGLArray.get());
517  break;
518  case f_vertexAttrib4v:
519  context.vertexAttrib4fv(index, webGLArray.get());
520  break;
521  }
522 
523  setDOMException(exec, ec);
524  return jsUndefined();
525  }
526 
527  Vector<float, 64> array;
528  if (!toVector(exec, exec->uncheckedArgument(1), array))
529  return throwTypeError(exec);
530 
531  switch (f) {
532  case f_uniform1v:
533  context.uniform1fv(location, array.data(), array.size(), ec);
534  break;
535  case f_uniform2v:
536  context.uniform2fv(location, array.data(), array.size(), ec);
537  break;
538  case f_uniform3v:
539  context.uniform3fv(location, array.data(), array.size(), ec);
540  break;
541  case f_uniform4v:
542  context.uniform4fv(location, array.data(), array.size(), ec);
543  break;
544  case f_vertexAttrib1v:
545  context.vertexAttrib1fv(index, array.data(), array.size());
546  break;
547  case f_vertexAttrib2v:
548  context.vertexAttrib2fv(index, array.data(), array.size());
549  break;
550  case f_vertexAttrib3v:
551  context.vertexAttrib3fv(index, array.data(), array.size());
552  break;
553  case f_vertexAttrib4v:
554  context.vertexAttrib4fv(index, array.data(), array.size());
555  break;
556  }
557 
558  setDOMException(exec, ec);
559  return jsUndefined();
560 }
561 
562 static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
563 {
564  if (exec->argumentCount() != 2)
565  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
566 
567  WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
568  if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
569  return throwTypeError(exec);
570 
571  RefPtr<Int32Array> webGLArray = toInt32Array(exec->uncheckedArgument(1));
572 
573  ExceptionCode ec = 0;
574  if (webGLArray) {
575  switch (f) {
576  case f_uniform1v:
577  context.uniform1iv(location, webGLArray.get(), ec);
578  break;
579  case f_uniform2v:
580  context.uniform2iv(location, webGLArray.get(), ec);
581  break;
582  case f_uniform3v:
583  context.uniform3iv(location, webGLArray.get(), ec);
584  break;
585  case f_uniform4v:
586  context.uniform4iv(location, webGLArray.get(), ec);
587  break;
588  default:
589  break;
590  }
591 
592  setDOMException(exec, ec);
593  return jsUndefined();
594  }
595 
596 
597  Vector<int, 64> array;
598  if (!toVector(exec, exec->uncheckedArgument(1), array))
599  return throwTypeError(exec);
600 
601  switch (f) {
602  case f_uniform1v:
603  context.uniform1iv(location, array.data(), array.size(), ec);
604  break;
605  case f_uniform2v:
606  context.uniform2iv(location, array.data(), array.size(), ec);
607  break;
608  case f_uniform3v:
609  context.uniform3iv(location, array.data(), array.size(), ec);
610  break;
611  case f_uniform4v:
612  context.uniform4iv(location, array.data(), array.size(), ec);
613  break;
614  default:
615  break;
616  }
617 
618  setDOMException(exec, ec);
619  return jsUndefined();
620 }
621 
622 static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
623 {
624  if (exec->argumentCount() != 3)
625  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
626 
627  WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
628  if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
629  return throwTypeError(exec);
630 
631  bool transpose = exec->uncheckedArgument(1).toBoolean(exec);
632  if (exec->hadException())
633  return jsUndefined();
634 
635  RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(2));
636 
637  ExceptionCode ec = 0;
638  if (webGLArray) {
639  switch (f) {
640  case f_uniformMatrix2fv:
641  context.uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
642  break;
643  case f_uniformMatrix3fv:
644  context.uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
645  break;
646  case f_uniformMatrix4fv:
647  context.uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
648  break;
649  }
650 
651  setDOMException(exec, ec);
652  return jsUndefined();
653  }
654 
655  Vector<float, 64> array;
656  if (!toVector(exec, exec->uncheckedArgument(2), array))
657  return throwTypeError(exec);
658 
659  switch (f) {
660  case f_uniformMatrix2fv:
661  context.uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
662  break;
663  case f_uniformMatrix3fv:
664  context.uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
665  break;
666  case f_uniformMatrix4fv:
667  context.uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
668  break;
669  }
670 
671  setDOMException(exec, ec);
672  return jsUndefined();
673 }
674 
675 JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec)
676 {
677  return dataFunctionf(f_uniform1v, exec, impl());
678 }
679 
680 JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec)
681 {
682  return dataFunctioni(f_uniform1v, exec, impl());
683 }
684 
685 JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec)
686 {
687  return dataFunctionf(f_uniform2v, exec, impl());
688 }
689 
690 JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec)
691 {
692  return dataFunctioni(f_uniform2v, exec, impl());
693 }
694 
695 JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec)
696 {
697  return dataFunctionf(f_uniform3v, exec, impl());
698 }
699 
700 JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec)
701 {
702  return dataFunctioni(f_uniform3v, exec, impl());
703 }
704 
705 JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec)
706 {
707  return dataFunctionf(f_uniform4v, exec, impl());
708 }
709 
710 JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec)
711 {
712  return dataFunctioni(f_uniform4v, exec, impl());
713 }
714 
715 JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec)
716 {
717  return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl());
718 }
719 
720 JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec)
721 {
722  return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl());
723 }
724 
725 JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec)
726 {
727  return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl());
728 }
729 
730 JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec)
731 {
732  return dataFunctionf(f_vertexAttrib1v, exec, impl());
733 }
734 
735 JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec)
736 {
737  return dataFunctionf(f_vertexAttrib2v, exec, impl());
738 }
739 
740 JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec)
741 {
742  return dataFunctionf(f_vertexAttrib3v, exec, impl());
743 }
744 
745 JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec)
746 {
747  return dataFunctionf(f_vertexAttrib4v, exec, impl());
748 }
749 
75040} // namespace WebCore
75141
75242#endif // ENABLE(WEBGL)
working copy

Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEBGL)
 29#include "JSWebGL2RenderingContext.h"
 30
 31using namespace JSC;
 32
 33namespace WebCore {
 34
 35void JSWebGL2RenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
 36{
 37 visitor.addOpaqueRoot(&impl());
 38}
 39
 40} // namespace WebCore
 41
 42#endif // ENABLE(WEBGL)
0

Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEBGL)
 29#include "JSWebGLRenderingContextBase.h"
 30
 31#include "ANGLEInstancedArrays.h"
 32#include "EXTBlendMinMax.h"
 33#include "EXTFragDepth.h"
 34#include "EXTShaderTextureLOD.h"
 35#include "EXTTextureFilterAnisotropic.h"
 36#include "EXTsRGB.h"
 37#include "ExceptionCode.h"
 38#include "HTMLCanvasElement.h"
 39#include "HTMLImageElement.h"
 40#include "JSANGLEInstancedArrays.h"
 41#include "JSEXTBlendMinMax.h"
 42#include "JSEXTFragDepth.h"
 43#include "JSEXTShaderTextureLOD.h"
 44#include "JSEXTTextureFilterAnisotropic.h"
 45#include "JSEXTsRGB.h"
 46#include "JSHTMLCanvasElement.h"
 47#include "JSHTMLImageElement.h"
 48#include "JSImageData.h"
 49#include "JSOESElementIndexUint.h"
 50#include "JSOESStandardDerivatives.h"
 51#include "JSOESTextureFloat.h"
 52#include "JSOESTextureFloatLinear.h"
 53#include "JSOESTextureHalfFloat.h"
 54#include "JSOESTextureHalfFloatLinear.h"
 55#include "JSOESVertexArrayObject.h"
 56#include "JSWebGLBuffer.h"
 57#include "JSWebGLCompressedTextureATC.h"
 58#include "JSWebGLCompressedTexturePVRTC.h"
 59#include "JSWebGLCompressedTextureS3TC.h"
 60#include "JSWebGLDebugRendererInfo.h"
 61#include "JSWebGLDebugShaders.h"
 62#include "JSWebGLDepthTexture.h"
 63#include "JSWebGLDrawBuffers.h"
 64#include "JSWebGLFramebuffer.h"
 65#include "JSWebGLLoseContext.h"
 66#include "JSWebGLProgram.h"
 67#include "JSWebGLRenderbuffer.h"
 68#include "JSWebGLShader.h"
 69#include "JSWebGLTexture.h"
 70#include "JSWebGLUniformLocation.h"
 71#include "JSWebGLVertexArrayObjectOES.h"
 72#include "JSWebKitCSSMatrix.h"
 73#include "NotImplemented.h"
 74#include "OESElementIndexUint.h"
 75#include "OESStandardDerivatives.h"
 76#include "OESTextureFloat.h"
 77#include "OESTextureFloatLinear.h"
 78#include "OESTextureHalfFloat.h"
 79#include "OESTextureHalfFloatLinear.h"
 80#include "OESVertexArrayObject.h"
 81#include "WebGLBuffer.h"
 82#include "WebGLCompressedTextureATC.h"
 83#include "WebGLCompressedTexturePVRTC.h"
 84#include "WebGLCompressedTextureS3TC.h"
 85#include "WebGLDebugRendererInfo.h"
 86#include "WebGLDebugShaders.h"
 87#include "WebGLDepthTexture.h"
 88#include "WebGLDrawBuffers.h"
 89#include "WebGLExtension.h"
 90#include "WebGLFramebuffer.h"
 91#include "WebGLGetInfo.h"
 92#include "WebGLLoseContext.h"
 93#include "WebGLProgram.h"
 94#include "WebGLRenderingContextBase.h"
 95#include "WebGLVertexArrayObjectOES.h"
 96#include <runtime/Error.h>
 97#include <runtime/JSTypedArrays.h>
 98#include <runtime/TypedArrayInlines.h>
 99#include <runtime/TypedArrays.h>
 100#include <wtf/FastMalloc.h>
 101
 102#if ENABLE(VIDEO)
 103#include "HTMLVideoElement.h"
 104#include "JSHTMLVideoElement.h"
 105#endif
 106
 107using namespace JSC;
 108
 109namespace WebCore {
 110
 111static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
 112{
 113 switch (info.getType()) {
 114 case WebGLGetInfo::kTypeBool:
 115 return jsBoolean(info.getBool());
 116 case WebGLGetInfo::kTypeBoolArray: {
 117 MarkedArgumentBuffer list;
 118 const Vector<bool>& value = info.getBoolArray();
 119 for (size_t ii = 0; ii < value.size(); ++ii)
 120 list.append(jsBoolean(value[ii]));
 121 return constructArray(exec, 0, globalObject, list);
 122 }
 123 case WebGLGetInfo::kTypeFloat:
 124 return jsNumber(info.getFloat());
 125 case WebGLGetInfo::kTypeInt:
 126 return jsNumber(info.getInt());
 127 case WebGLGetInfo::kTypeNull:
 128 return jsNull();
 129 case WebGLGetInfo::kTypeString:
 130 return jsStringWithCache(exec, info.getString());
 131 case WebGLGetInfo::kTypeUnsignedInt:
 132 return jsNumber(info.getUnsignedInt());
 133 case WebGLGetInfo::kTypeWebGLBuffer:
 134 return toJS(exec, globalObject, info.getWebGLBuffer());
 135 case WebGLGetInfo::kTypeWebGLFloatArray:
 136 return toJS(exec, globalObject, info.getWebGLFloatArray());
 137 case WebGLGetInfo::kTypeWebGLFramebuffer:
 138 return toJS(exec, globalObject, info.getWebGLFramebuffer());
 139 case WebGLGetInfo::kTypeWebGLIntArray:
 140 return toJS(exec, globalObject, info.getWebGLIntArray());
 141 // FIXME: implement WebGLObjectArray
 142 // case WebGLGetInfo::kTypeWebGLObjectArray:
 143 case WebGLGetInfo::kTypeWebGLProgram:
 144 return toJS(exec, globalObject, info.getWebGLProgram());
 145 case WebGLGetInfo::kTypeWebGLRenderbuffer:
 146 return toJS(exec, globalObject, info.getWebGLRenderbuffer());
 147 case WebGLGetInfo::kTypeWebGLTexture:
 148 return toJS(exec, globalObject, info.getWebGLTexture());
 149 case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
 150 return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
 151 case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
 152 return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
 153 case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
 154 return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
 155 default:
 156 notImplemented();
 157 return jsUndefined();
 158 }
 159}
 160
 161enum ObjectType {
 162 kBuffer, kRenderbuffer, kTexture, kVertexAttrib
 163};
 164
 165static JSValue getObjectParameter(JSWebGLRenderingContextBase* obj, ExecState* exec, ObjectType objectType)
 166{
 167 if (exec->argumentCount() != 2)
 168 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 169
 170 ExceptionCode ec = 0;
 171 WebGLRenderingContextBase& context = obj->impl();
 172 unsigned target = exec->uncheckedArgument(0).toInt32(exec);
 173 if (exec->hadException())
 174 return jsUndefined();
 175 unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
 176 if (exec->hadException())
 177 return jsUndefined();
 178 WebGLGetInfo info;
 179 switch (objectType) {
 180 case kBuffer:
 181 info = context.getBufferParameter(target, pname, ec);
 182 break;
 183 case kRenderbuffer:
 184 info = context.getRenderbufferParameter(target, pname, ec);
 185 break;
 186 case kTexture:
 187 info = context.getTexParameter(target, pname, ec);
 188 break;
 189 case kVertexAttrib:
 190 // target => index
 191 info = context.getVertexAttrib(target, pname, ec);
 192 break;
 193 default:
 194 notImplemented();
 195 break;
 196 }
 197 if (ec) {
 198 setDOMException(exec, ec);
 199 return jsUndefined();
 200 }
 201 return toJS(exec, obj->globalObject(), info);
 202}
 203
 204enum WhichProgramCall {
 205 kProgramParameter, kUniform
 206};
 207
 208static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
 209{
 210 if (!extension)
 211 return jsNull();
 212 switch (extension->getName()) {
 213 case WebGLExtension::WebGLLoseContextName:
 214 return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
 215 case WebGLExtension::EXTShaderTextureLODName:
 216 return toJS(exec, globalObject, static_cast<EXTShaderTextureLOD*>(extension));
 217 case WebGLExtension::EXTTextureFilterAnisotropicName:
 218 return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
 219 case WebGLExtension::EXTsRGBName:
 220 return toJS(exec, globalObject, static_cast<EXTsRGB*>(extension));
 221 case WebGLExtension::EXTFragDepthName:
 222 return toJS(exec, globalObject, static_cast<EXTFragDepth*>(extension));
 223 case WebGLExtension::EXTBlendMinMaxName:
 224 return toJS(exec, globalObject, static_cast<EXTBlendMinMax*>(extension));
 225 case WebGLExtension::OESStandardDerivativesName:
 226 return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
 227 case WebGLExtension::OESTextureFloatName:
 228 return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
 229 case WebGLExtension::OESTextureFloatLinearName:
 230 return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension));
 231 case WebGLExtension::OESTextureHalfFloatName:
 232 return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
 233 case WebGLExtension::OESTextureHalfFloatLinearName:
 234 return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
 235 case WebGLExtension::OESVertexArrayObjectName:
 236 return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
 237 case WebGLExtension::OESElementIndexUintName:
 238 return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
 239 case WebGLExtension::WebGLDebugRendererInfoName:
 240 return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
 241 case WebGLExtension::WebGLDebugShadersName:
 242 return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
 243 case WebGLExtension::WebGLCompressedTextureATCName:
 244 return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
 245 case WebGLExtension::WebGLCompressedTexturePVRTCName:
 246 return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
 247 case WebGLExtension::WebGLCompressedTextureS3TCName:
 248 return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
 249 case WebGLExtension::WebGLDepthTextureName:
 250 return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
 251 case WebGLExtension::WebGLDrawBuffersName:
 252 return toJS(exec, globalObject, static_cast<WebGLDrawBuffers*>(extension));
 253 case WebGLExtension::ANGLEInstancedArraysName:
 254 return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension));
 255 }
 256 ASSERT_NOT_REACHED();
 257 return jsNull();
 258}
 259
 260void JSWebGLRenderingContextBase::visitAdditionalChildren(SlotVisitor& visitor)
 261{
 262 visitor.addOpaqueRoot(&impl());
 263}
 264
 265JSValue JSWebGLRenderingContextBase::getAttachedShaders(ExecState* exec)
 266{
 267 if (exec->argumentCount() < 1)
 268 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 269 ExceptionCode ec = 0;
 270 WebGLRenderingContextBase& context = impl();
 271 WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
 272 if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
 273 return throwTypeError(exec);
 274 Vector<RefPtr<WebGLShader>> shaders;
 275 bool succeed = context.getAttachedShaders(program, shaders, ec);
 276 if (ec) {
 277 setDOMException(exec, ec);
 278 return jsNull();
 279 }
 280 if (!succeed)
 281 return jsNull();
 282 JSC::MarkedArgumentBuffer list;
 283 for (size_t ii = 0; ii < shaders.size(); ++ii)
 284 list.append(toJS(exec, globalObject(), shaders[ii].get()));
 285 return constructArray(exec, 0, globalObject(), list);
 286}
 287
 288JSValue JSWebGLRenderingContextBase::getExtension(ExecState* exec)
 289{
 290 if (exec->argumentCount() < 1)
 291 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 292
 293 WebGLRenderingContextBase& context = impl();
 294 const String name = exec->uncheckedArgument(0).toString(exec)->value(exec);
 295 if (exec->hadException())
 296 return jsUndefined();
 297 WebGLExtension* extension = context.getExtension(name);
 298 return toJS(exec, globalObject(), extension);
 299}
 300
 301JSValue JSWebGLRenderingContextBase::getBufferParameter(ExecState* exec)
 302{
 303 return getObjectParameter(this, exec, kBuffer);
 304}
 305
 306JSValue JSWebGLRenderingContextBase::getFramebufferAttachmentParameter(ExecState* exec)
 307{
 308 if (exec->argumentCount() != 3)
 309 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 310
 311 ExceptionCode ec = 0;
 312 WebGLRenderingContextBase& context = impl();
 313 unsigned target = exec->uncheckedArgument(0).toInt32(exec);
 314 if (exec->hadException())
 315 return jsUndefined();
 316 unsigned attachment = exec->uncheckedArgument(1).toInt32(exec);
 317 if (exec->hadException())
 318 return jsUndefined();
 319 unsigned pname = exec->uncheckedArgument(2).toInt32(exec);
 320 if (exec->hadException())
 321 return jsUndefined();
 322 WebGLGetInfo info = context.getFramebufferAttachmentParameter(target, attachment, pname, ec);
 323 if (ec) {
 324 setDOMException(exec, ec);
 325 return jsUndefined();
 326 }
 327 return toJS(exec, globalObject(), info);
 328}
 329
 330JSValue JSWebGLRenderingContextBase::getParameter(ExecState* exec)
 331{
 332 if (exec->argumentCount() != 1)
 333 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 334
 335 ExceptionCode ec = 0;
 336 WebGLRenderingContextBase& context = impl();
 337 unsigned pname = exec->uncheckedArgument(0).toInt32(exec);
 338 if (exec->hadException())
 339 return jsUndefined();
 340 WebGLGetInfo info = context.getParameter(pname, ec);
 341 if (ec) {
 342 setDOMException(exec, ec);
 343 return jsUndefined();
 344 }
 345 return toJS(exec, globalObject(), info);
 346}
 347
 348JSValue JSWebGLRenderingContextBase::getProgramParameter(ExecState* exec)
 349{
 350 if (exec->argumentCount() != 2)
 351 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 352
 353 ExceptionCode ec = 0;
 354 WebGLRenderingContextBase& context = impl();
 355 WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
 356 if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
 357 return throwTypeError(exec);
 358 unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
 359 if (exec->hadException())
 360 return jsUndefined();
 361 WebGLGetInfo info = context.getProgramParameter(program, pname, ec);
 362 if (ec) {
 363 setDOMException(exec, ec);
 364 return jsUndefined();
 365 }
 366 return toJS(exec, globalObject(), info);
 367}
 368
 369JSValue JSWebGLRenderingContextBase::getRenderbufferParameter(ExecState* exec)
 370{
 371 return getObjectParameter(this, exec, kRenderbuffer);
 372}
 373
 374JSValue JSWebGLRenderingContextBase::getShaderParameter(ExecState* exec)
 375{
 376 if (exec->argumentCount() != 2)
 377 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 378
 379 ExceptionCode ec = 0;
 380 WebGLRenderingContextBase& context = impl();
 381 if (!exec->uncheckedArgument(0).isUndefinedOrNull() && !exec->uncheckedArgument(0).inherits(JSWebGLShader::info()))
 382 return throwTypeError(exec);
 383 WebGLShader* shader = JSWebGLShader::toWrapped(exec->uncheckedArgument(0));
 384 unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
 385 if (exec->hadException())
 386 return jsUndefined();
 387 WebGLGetInfo info = context.getShaderParameter(shader, pname, ec);
 388 if (ec) {
 389 setDOMException(exec, ec);
 390 return jsUndefined();
 391 }
 392 return toJS(exec, globalObject(), info);
 393}
 394
 395JSValue JSWebGLRenderingContextBase::getSupportedExtensions(ExecState* exec)
 396{
 397 WebGLRenderingContextBase& context = impl();
 398 if (context.isContextLost())
 399 return jsNull();
 400 Vector<String> value = context.getSupportedExtensions();
 401 MarkedArgumentBuffer list;
 402 for (size_t ii = 0; ii < value.size(); ++ii)
 403 list.append(jsStringWithCache(exec, value[ii]));
 404 return constructArray(exec, 0, globalObject(), list);
 405}
 406
 407JSValue JSWebGLRenderingContextBase::getTexParameter(ExecState* exec)
 408{
 409 return getObjectParameter(this, exec, kTexture);
 410}
 411
 412JSValue JSWebGLRenderingContextBase::getUniform(ExecState* exec)
 413{
 414 if (exec->argumentCount() != 2)
 415 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 416
 417 ExceptionCode ec = 0;
 418 WebGLRenderingContextBase& context = impl();
 419 WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
 420 if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
 421 return throwTypeError(exec);
 422 WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(1));
 423 if (!location && !exec->uncheckedArgument(1).isUndefinedOrNull())
 424 return throwTypeError(exec);
 425 WebGLGetInfo info = context.getUniform(program, location, ec);
 426 if (ec) {
 427 setDOMException(exec, ec);
 428 return jsUndefined();
 429 }
 430 return toJS(exec, globalObject(), info);
 431}
 432
 433JSValue JSWebGLRenderingContextBase::getVertexAttrib(ExecState* exec)
 434{
 435 return getObjectParameter(this, exec, kVertexAttrib);
 436}
 437
 438template<typename T, size_t inlineCapacity>
 439bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
 440{
 441 if (!value.isObject())
 442 return false;
 443
 444 JSC::JSObject* object = asObject(value);
 445 int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec);
 446
 447 if (!vector.tryReserveCapacity(length))
 448 return false;
 449 vector.resize(length);
 450
 451 for (int32_t i = 0; i < length; ++i) {
 452 JSC::JSValue v = object->get(exec, i);
 453 if (exec->hadException())
 454 return false;
 455 vector[i] = static_cast<T>(v.toNumber(exec));
 456 }
 457
 458 return true;
 459}
 460
 461enum DataFunctionToCall {
 462 f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
 463 f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
 464};
 465
 466enum DataFunctionMatrixToCall {
 467 f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
 468};
 469
 470static bool functionForUniform(DataFunctionToCall f)
 471{
 472 switch (f) {
 473 case f_uniform1v:
 474 case f_uniform2v:
 475 case f_uniform3v:
 476 case f_uniform4v:
 477 return true;
 478 default: break;
 479 }
 480 return false;
 481}
 482
 483static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContextBase& context)
 484{
 485 if (exec->argumentCount() != 2)
 486 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 487
 488 WebGLUniformLocation* location = 0;
 489 long index = -1;
 490
 491 if (functionForUniform(f)) {
 492 location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
 493 if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
 494 return throwTypeError(exec);
 495 } else
 496 index = exec->uncheckedArgument(0).toInt32(exec);
 497
 498 if (exec->hadException())
 499 return jsUndefined();
 500
 501 RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1));
 502 if (exec->hadException())
 503 return jsUndefined();
 504
 505 ExceptionCode ec = 0;
 506 if (webGLArray) {
 507 switch (f) {
 508 case f_uniform1v:
 509 context.uniform1fv(location, webGLArray.get(), ec);
 510 break;
 511 case f_uniform2v:
 512 context.uniform2fv(location, webGLArray.get(), ec);
 513 break;
 514 case f_uniform3v:
 515 context.uniform3fv(location, webGLArray.get(), ec);
 516 break;
 517 case f_uniform4v:
 518 context.uniform4fv(location, webGLArray.get(), ec);
 519 break;
 520 case f_vertexAttrib1v:
 521 context.vertexAttrib1fv(index, webGLArray.get());
 522 break;
 523 case f_vertexAttrib2v:
 524 context.vertexAttrib2fv(index, webGLArray.get());
 525 break;
 526 case f_vertexAttrib3v:
 527 context.vertexAttrib3fv(index, webGLArray.get());
 528 break;
 529 case f_vertexAttrib4v:
 530 context.vertexAttrib4fv(index, webGLArray.get());
 531 break;
 532 }
 533
 534 setDOMException(exec, ec);
 535 return jsUndefined();
 536 }
 537
 538 Vector<float, 64> array;
 539 if (!toVector(exec, exec->uncheckedArgument(1), array))
 540 return throwTypeError(exec);
 541
 542 switch (f) {
 543 case f_uniform1v:
 544 context.uniform1fv(location, array.data(), array.size(), ec);
 545 break;
 546 case f_uniform2v:
 547 context.uniform2fv(location, array.data(), array.size(), ec);
 548 break;
 549 case f_uniform3v:
 550 context.uniform3fv(location, array.data(), array.size(), ec);
 551 break;
 552 case f_uniform4v:
 553 context.uniform4fv(location, array.data(), array.size(), ec);
 554 break;
 555 case f_vertexAttrib1v:
 556 context.vertexAttrib1fv(index, array.data(), array.size());
 557 break;
 558 case f_vertexAttrib2v:
 559 context.vertexAttrib2fv(index, array.data(), array.size());
 560 break;
 561 case f_vertexAttrib3v:
 562 context.vertexAttrib3fv(index, array.data(), array.size());
 563 break;
 564 case f_vertexAttrib4v:
 565 context.vertexAttrib4fv(index, array.data(), array.size());
 566 break;
 567 }
 568
 569 setDOMException(exec, ec);
 570 return jsUndefined();
 571}
 572
 573static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContextBase& context)
 574{
 575 if (exec->argumentCount() != 2)
 576 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 577
 578 WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
 579 if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
 580 return throwTypeError(exec);
 581
 582 RefPtr<Int32Array> webGLArray = toInt32Array(exec->uncheckedArgument(1));
 583
 584 ExceptionCode ec = 0;
 585 if (webGLArray) {
 586 switch (f) {
 587 case f_uniform1v:
 588 context.uniform1iv(location, webGLArray.get(), ec);
 589 break;
 590 case f_uniform2v:
 591 context.uniform2iv(location, webGLArray.get(), ec);
 592 break;
 593 case f_uniform3v:
 594 context.uniform3iv(location, webGLArray.get(), ec);
 595 break;
 596 case f_uniform4v:
 597 context.uniform4iv(location, webGLArray.get(), ec);
 598 break;
 599 default:
 600 break;
 601 }
 602
 603 setDOMException(exec, ec);
 604 return jsUndefined();
 605 }
 606
 607
 608 Vector<int, 64> array;
 609 if (!toVector(exec, exec->uncheckedArgument(1), array))
 610 return throwTypeError(exec);
 611
 612 switch (f) {
 613 case f_uniform1v:
 614 context.uniform1iv(location, array.data(), array.size(), ec);
 615 break;
 616 case f_uniform2v:
 617 context.uniform2iv(location, array.data(), array.size(), ec);
 618 break;
 619 case f_uniform3v:
 620 context.uniform3iv(location, array.data(), array.size(), ec);
 621 break;
 622 case f_uniform4v:
 623 context.uniform4iv(location, array.data(), array.size(), ec);
 624 break;
 625 default:
 626 break;
 627 }
 628
 629 setDOMException(exec, ec);
 630 return jsUndefined();
 631}
 632
 633static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContextBase& context)
 634{
 635 if (exec->argumentCount() != 3)
 636 return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
 637
 638 WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
 639 if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
 640 return throwTypeError(exec);
 641
 642 bool transpose = exec->uncheckedArgument(1).toBoolean(exec);
 643 if (exec->hadException())
 644 return jsUndefined();
 645
 646 RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(2));
 647
 648 ExceptionCode ec = 0;
 649 if (webGLArray) {
 650 switch (f) {
 651 case f_uniformMatrix2fv:
 652 context.uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
 653 break;
 654 case f_uniformMatrix3fv:
 655 context.uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
 656 break;
 657 case f_uniformMatrix4fv:
 658 context.uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
 659 break;
 660 }
 661
 662 setDOMException(exec, ec);
 663 return jsUndefined();
 664 }
 665
 666 Vector<float, 64> array;
 667 if (!toVector(exec, exec->uncheckedArgument(2), array))
 668 return throwTypeError(exec);
 669
 670 switch (f) {
 671 case f_uniformMatrix2fv:
 672 context.uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
 673 break;
 674 case f_uniformMatrix3fv:
 675 context.uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
 676 break;
 677 case f_uniformMatrix4fv:
 678 context.uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
 679 break;
 680 }
 681
 682 setDOMException(exec, ec);
 683 return jsUndefined();
 684}
 685
 686JSC::JSValue JSWebGLRenderingContextBase::uniform1fv(JSC::ExecState* exec)
 687{
 688 return dataFunctionf(f_uniform1v, exec, impl());
 689}
 690
 691JSC::JSValue JSWebGLRenderingContextBase::uniform1iv(JSC::ExecState* exec)
 692{
 693 return dataFunctioni(f_uniform1v, exec, impl());
 694}
 695
 696JSC::JSValue JSWebGLRenderingContextBase::uniform2fv(JSC::ExecState* exec)
 697{
 698 return dataFunctionf(f_uniform2v, exec, impl());
 699}
 700
 701JSC::JSValue JSWebGLRenderingContextBase::uniform2iv(JSC::ExecState* exec)
 702{
 703 return dataFunctioni(f_uniform2v, exec, impl());
 704}
 705
 706JSC::JSValue JSWebGLRenderingContextBase::uniform3fv(JSC::ExecState* exec)
 707{
 708 return dataFunctionf(f_uniform3v, exec, impl());
 709}
 710
 711JSC::JSValue JSWebGLRenderingContextBase::uniform3iv(JSC::ExecState* exec)
 712{
 713 return dataFunctioni(f_uniform3v, exec, impl());
 714}
 715
 716JSC::JSValue JSWebGLRenderingContextBase::uniform4fv(JSC::ExecState* exec)
 717{
 718 return dataFunctionf(f_uniform4v, exec, impl());
 719}
 720
 721JSC::JSValue JSWebGLRenderingContextBase::uniform4iv(JSC::ExecState* exec)
 722{
 723 return dataFunctioni(f_uniform4v, exec, impl());
 724}
 725
 726JSC::JSValue JSWebGLRenderingContextBase::uniformMatrix2fv(JSC::ExecState* exec)
 727{
 728 return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl());
 729}
 730
 731JSC::JSValue JSWebGLRenderingContextBase::uniformMatrix3fv(JSC::ExecState* exec)
 732{
 733 return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl());
 734}
 735
 736JSC::JSValue JSWebGLRenderingContextBase::uniformMatrix4fv(JSC::ExecState* exec)
 737{
 738 return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl());
 739}
 740
 741JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib1fv(JSC::ExecState* exec)
 742{
 743 return dataFunctionf(f_vertexAttrib1v, exec, impl());
 744}
 745
 746JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib2fv(JSC::ExecState* exec)
 747{
 748 return dataFunctionf(f_vertexAttrib2v, exec, impl());
 749}
 750
 751JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib3fv(JSC::ExecState* exec)
 752{
 753 return dataFunctionf(f_vertexAttrib3v, exec, impl());
 754}
 755
 756JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib4fv(JSC::ExecState* exec)
 757{
 758 return dataFunctionf(f_vertexAttrib4v, exec, impl());
 759}
 760
 761} // namespace WebCore
 762
 763#endif // ENABLE(WEBGL)
0

Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp

1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if ENABLE(WEBGL)
29 
30 #include "JSWebGLRenderingContext.h"
31 
32 #include "ANGLEInstancedArrays.h"
33 #include "EXTBlendMinMax.h"
34 #include "EXTFragDepth.h"
35 #include "EXTShaderTextureLOD.h"
36 #include "EXTTextureFilterAnisotropic.h"
37 #include "EXTsRGB.h"
38 #include "ExceptionCode.h"
39 #include "HTMLCanvasElement.h"
40 #include "HTMLImageElement.h"
41 #include "JSANGLEInstancedArrays.h"
42 #include "JSEXTBlendMinMax.h"
43 #include "JSEXTFragDepth.h"
44 #include "JSEXTShaderTextureLOD.h"
45 #include "JSEXTTextureFilterAnisotropic.h"
46 #include "JSEXTsRGB.h"
47 #include "JSHTMLCanvasElement.h"
48 #include "JSHTMLImageElement.h"
49 #include "JSImageData.h"
50 #include "JSOESElementIndexUint.h"
51 #include "JSOESStandardDerivatives.h"
52 #include "JSOESTextureFloat.h"
53 #include "JSOESTextureFloatLinear.h"
54 #include "JSOESTextureHalfFloat.h"
55 #include "JSOESTextureHalfFloatLinear.h"
56 #include "JSOESVertexArrayObject.h"
57 #include "JSWebGLBuffer.h"
58 #include "JSWebGLCompressedTextureATC.h"
59 #include "JSWebGLCompressedTexturePVRTC.h"
60 #include "JSWebGLCompressedTextureS3TC.h"
61 #include "JSWebGLDebugRendererInfo.h"
62 #include "JSWebGLDebugShaders.h"
63 #include "JSWebGLDepthTexture.h"
64 #include "JSWebGLDrawBuffers.h"
65 #include "JSWebGLFramebuffer.h"
66 #include "JSWebGLLoseContext.h"
67 #include "JSWebGLProgram.h"
68 #include "JSWebGLRenderbuffer.h"
69 #include "JSWebGLShader.h"
70 #include "JSWebGLTexture.h"
71 #include "JSWebGLUniformLocation.h"
72 #include "JSWebGLVertexArrayObjectOES.h"
73 #include "JSWebKitCSSMatrix.h"
74 #include "NotImplemented.h"
75 #include "OESElementIndexUint.h"
76 #include "OESStandardDerivatives.h"
77 #include "OESTextureFloat.h"
78 #include "OESTextureFloatLinear.h"
79 #include "OESTextureHalfFloat.h"
80 #include "OESTextureHalfFloatLinear.h"
81 #include "OESVertexArrayObject.h"
82 #include "WebGLBuffer.h"
83 #include "WebGLCompressedTextureATC.h"
84 #include "WebGLCompressedTexturePVRTC.h"
85 #include "WebGLCompressedTextureS3TC.h"
86 #include "WebGLDebugRendererInfo.h"
87 #include "WebGLDebugShaders.h"
88 #include "WebGLDepthTexture.h"
89 #include "WebGLDrawBuffers.h"
90 #include "WebGLExtension.h"
91 #include "WebGLFramebuffer.h"
92 #include "WebGLGetInfo.h"
93 #include "WebGLLoseContext.h"
94 #include "WebGLProgram.h"
95 #include "WebGLRenderingContext.h"
96 #include "WebGLVertexArrayObjectOES.h"
97 #include <runtime/Error.h>
98 #include <runtime/JSTypedArrays.h>
99 #include <runtime/TypedArrayInlines.h>
100 #include <runtime/TypedArrays.h>
101 #include <wtf/FastMalloc.h>
102 
103 #if ENABLE(VIDEO)
104 #include "HTMLVideoElement.h"
105 #include "JSHTMLVideoElement.h"
106 #endif
107 
108 using namespace JSC;
109 
110 namespace WebCore {
111 
112 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
113 {
114  switch (info.getType()) {
115  case WebGLGetInfo::kTypeBool:
116  return jsBoolean(info.getBool());
117  case WebGLGetInfo::kTypeBoolArray: {
118  MarkedArgumentBuffer list;
119  const Vector<bool>& value = info.getBoolArray();
120  for (size_t ii = 0; ii < value.size(); ++ii)
121  list.append(jsBoolean(value[ii]));
122  return constructArray(exec, 0, globalObject, list);
123  }
124  case WebGLGetInfo::kTypeFloat:
125  return jsNumber(info.getFloat());
126  case WebGLGetInfo::kTypeInt:
127  return jsNumber(info.getInt());
128  case WebGLGetInfo::kTypeNull:
129  return jsNull();
130  case WebGLGetInfo::kTypeString:
131  return jsStringWithCache(exec, info.getString());
132  case WebGLGetInfo::kTypeUnsignedInt:
133  return jsNumber(info.getUnsignedInt());
134  case WebGLGetInfo::kTypeWebGLBuffer:
135  return toJS(exec, globalObject, info.getWebGLBuffer());
136  case WebGLGetInfo::kTypeWebGLFloatArray:
137  return toJS(exec, globalObject, info.getWebGLFloatArray());
138  case WebGLGetInfo::kTypeWebGLFramebuffer:
139  return toJS(exec, globalObject, info.getWebGLFramebuffer());
140  case WebGLGetInfo::kTypeWebGLIntArray:
141  return toJS(exec, globalObject, info.getWebGLIntArray());
142  // FIXME: implement WebGLObjectArray
143  // case WebGLGetInfo::kTypeWebGLObjectArray:
144  case WebGLGetInfo::kTypeWebGLProgram:
145  return toJS(exec, globalObject, info.getWebGLProgram());
146  case WebGLGetInfo::kTypeWebGLRenderbuffer:
147  return toJS(exec, globalObject, info.getWebGLRenderbuffer());
148  case WebGLGetInfo::kTypeWebGLTexture:
149  return toJS(exec, globalObject, info.getWebGLTexture());
150  case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
151  return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
152  case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
153  return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
154  case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
155  return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
156  default:
157  notImplemented();
158  return jsUndefined();
159  }
160 }
161 
162 enum ObjectType {
163  kBuffer, kRenderbuffer, kTexture, kVertexAttrib
164 };
165 
166 static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, ObjectType objectType)
167 {
168  if (exec->argumentCount() != 2)
169  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
170 
171  ExceptionCode ec = 0;
172  WebGLRenderingContext& context = obj->impl();
173  unsigned target = exec->uncheckedArgument(0).toInt32(exec);
174  if (exec->hadException())
175  return jsUndefined();
176  unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
177  if (exec->hadException())
178  return jsUndefined();
179  WebGLGetInfo info;
180  switch (objectType) {
181  case kBuffer:
182  info = context.getBufferParameter(target, pname, ec);
183  break;
184  case kRenderbuffer:
185  info = context.getRenderbufferParameter(target, pname, ec);
186  break;
187  case kTexture:
188  info = context.getTexParameter(target, pname, ec);
189  break;
190  case kVertexAttrib:
191  // target => index
192  info = context.getVertexAttrib(target, pname, ec);
193  break;
194  default:
195  notImplemented();
196  break;
197  }
198  if (ec) {
199  setDOMException(exec, ec);
200  return jsUndefined();
201  }
202  return toJS(exec, obj->globalObject(), info);
203 }
204 
205 enum WhichProgramCall {
206  kProgramParameter, kUniform
207 };
208 
209 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
210 {
211  if (!extension)
212  return jsNull();
213  switch (extension->getName()) {
214  case WebGLExtension::WebGLLoseContextName:
215  return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
216  case WebGLExtension::EXTShaderTextureLODName:
217  return toJS(exec, globalObject, static_cast<EXTShaderTextureLOD*>(extension));
218  case WebGLExtension::EXTTextureFilterAnisotropicName:
219  return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
220  case WebGLExtension::EXTsRGBName:
221  return toJS(exec, globalObject, static_cast<EXTsRGB*>(extension));
222  case WebGLExtension::EXTFragDepthName:
223  return toJS(exec, globalObject, static_cast<EXTFragDepth*>(extension));
224  case WebGLExtension::EXTBlendMinMaxName:
225  return toJS(exec, globalObject, static_cast<EXTBlendMinMax*>(extension));
226  case WebGLExtension::OESStandardDerivativesName:
227  return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
228  case WebGLExtension::OESTextureFloatName:
229  return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
230  case WebGLExtension::OESTextureFloatLinearName:
231  return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension));
232  case WebGLExtension::OESTextureHalfFloatName:
233  return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
234  case WebGLExtension::OESTextureHalfFloatLinearName:
235  return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
236  case WebGLExtension::OESVertexArrayObjectName:
237  return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
238  case WebGLExtension::OESElementIndexUintName:
239  return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
240  case WebGLExtension::WebGLDebugRendererInfoName:
241  return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
242  case WebGLExtension::WebGLDebugShadersName:
243  return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
244  case WebGLExtension::WebGLCompressedTextureATCName:
245  return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
246  case WebGLExtension::WebGLCompressedTexturePVRTCName:
247  return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
248  case WebGLExtension::WebGLCompressedTextureS3TCName:
249  return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
250  case WebGLExtension::WebGLDepthTextureName:
251  return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
252  case WebGLExtension::WebGLDrawBuffersName:
253  return toJS(exec, globalObject, static_cast<WebGLDrawBuffers*>(extension));
254  case WebGLExtension::ANGLEInstancedArraysName:
255  return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension));
256  }
257  ASSERT_NOT_REACHED();
258  return jsNull();
259 }
260 
261 void JSWebGLRenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
262 {
263  visitor.addOpaqueRoot(&impl());
264 }
265 
266 JSValue JSWebGLRenderingContext::getAttachedShaders(ExecState* exec)
267 {
268  if (exec->argumentCount() < 1)
269  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
270  ExceptionCode ec = 0;
271  WebGLRenderingContext& context = impl();
272  WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
273  if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
274  return throwTypeError(exec);
275  Vector<RefPtr<WebGLShader>> shaders;
276  bool succeed = context.getAttachedShaders(program, shaders, ec);
277  if (ec) {
278  setDOMException(exec, ec);
279  return jsNull();
280  }
281  if (!succeed)
282  return jsNull();
283  JSC::MarkedArgumentBuffer list;
284  for (size_t ii = 0; ii < shaders.size(); ++ii)
285  list.append(toJS(exec, globalObject(), shaders[ii].get()));
286  return constructArray(exec, 0, globalObject(), list);
287 }
288 
289 JSValue JSWebGLRenderingContext::getExtension(ExecState* exec)
290 {
291  if (exec->argumentCount() < 1)
292  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
293 
294  WebGLRenderingContext& context = impl();
295  const String name = exec->uncheckedArgument(0).toString(exec)->value(exec);
296  if (exec->hadException())
297  return jsUndefined();
298  WebGLExtension* extension = context.getExtension(name);
299  return toJS(exec, globalObject(), extension);
300 }
301 
302 JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec)
303 {
304  return getObjectParameter(this, exec, kBuffer);
305 }
306 
307 JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec)
308 {
309  if (exec->argumentCount() != 3)
310  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
311 
312  ExceptionCode ec = 0;
313  WebGLRenderingContext& context = impl();
314  unsigned target = exec->uncheckedArgument(0).toInt32(exec);
315  if (exec->hadException())
316  return jsUndefined();
317  unsigned attachment = exec->uncheckedArgument(1).toInt32(exec);
318  if (exec->hadException())
319  return jsUndefined();
320  unsigned pname = exec->uncheckedArgument(2).toInt32(exec);
321  if (exec->hadException())
322  return jsUndefined();
323  WebGLGetInfo info = context.getFramebufferAttachmentParameter(target, attachment, pname, ec);
324  if (ec) {
325  setDOMException(exec, ec);
326  return jsUndefined();
327  }
328  return toJS(exec, globalObject(), info);
329 }
330 
331 JSValue JSWebGLRenderingContext::getParameter(ExecState* exec)
332 {
333  if (exec->argumentCount() != 1)
334  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
335 
336  ExceptionCode ec = 0;
337  WebGLRenderingContext& context = impl();
338  unsigned pname = exec->uncheckedArgument(0).toInt32(exec);
339  if (exec->hadException())
340  return jsUndefined();
341  WebGLGetInfo info = context.getParameter(pname, ec);
342  if (ec) {
343  setDOMException(exec, ec);
344  return jsUndefined();
345  }
346  return toJS(exec, globalObject(), info);
347 }
348 
349 JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec)
350 {
351  if (exec->argumentCount() != 2)
352  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
353 
354  ExceptionCode ec = 0;
355  WebGLRenderingContext& context = impl();
356  WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
357  if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
358  return throwTypeError(exec);
359  unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
360  if (exec->hadException())
361  return jsUndefined();
362  WebGLGetInfo info = context.getProgramParameter(program, pname, ec);
363  if (ec) {
364  setDOMException(exec, ec);
365  return jsUndefined();
366  }
367  return toJS(exec, globalObject(), info);
368 }
369 
370 JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec)
371 {
372  return getObjectParameter(this, exec, kRenderbuffer);
373 }
374 
375 JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec)
376 {
377  if (exec->argumentCount() != 2)
378  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
379 
380  ExceptionCode ec = 0;
381  WebGLRenderingContext& context = impl();
382  if (!exec->uncheckedArgument(0).isUndefinedOrNull() && !exec->uncheckedArgument(0).inherits(JSWebGLShader::info()))
383  return throwTypeError(exec);
384  WebGLShader* shader = JSWebGLShader::toWrapped(exec->uncheckedArgument(0));
385  unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
386  if (exec->hadException())
387  return jsUndefined();
388  WebGLGetInfo info = context.getShaderParameter(shader, pname, ec);
389  if (ec) {
390  setDOMException(exec, ec);
391  return jsUndefined();
392  }
393  return toJS(exec, globalObject(), info);
394 }
395 
396 JSValue JSWebGLRenderingContext::getSupportedExtensions(ExecState* exec)
397 {
398  WebGLRenderingContext& context = impl();
399  if (context.isContextLost())
400  return jsNull();
401  Vector<String> value = context.getSupportedExtensions();
402  MarkedArgumentBuffer list;
403  for (size_t ii = 0; ii < value.size(); ++ii)
404  list.append(jsStringWithCache(exec, value[ii]));
405  return constructArray(exec, 0, globalObject(), list);
406 }
407 
408 JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec)
409 {
410  return getObjectParameter(this, exec, kTexture);
411 }
412 
413 JSValue JSWebGLRenderingContext::getUniform(ExecState* exec)
414 {
415  if (exec->argumentCount() != 2)
416  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
417 
418  ExceptionCode ec = 0;
419  WebGLRenderingContext& context = impl();
420  WebGLProgram* program = JSWebGLProgram::toWrapped(exec->uncheckedArgument(0));
421  if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
422  return throwTypeError(exec);
423  WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(1));
424  if (!location && !exec->uncheckedArgument(1).isUndefinedOrNull())
425  return throwTypeError(exec);
426  WebGLGetInfo info = context.getUniform(program, location, ec);
427  if (ec) {
428  setDOMException(exec, ec);
429  return jsUndefined();
430  }
431  return toJS(exec, globalObject(), info);
432 }
433 
434 JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec)
435 {
436  return getObjectParameter(this, exec, kVertexAttrib);
437 }
438 
439 template<typename T, size_t inlineCapacity>
440 bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
441 {
442  if (!value.isObject())
443  return false;
444 
445  JSC::JSObject* object = asObject(value);
446  int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec);
447 
448  if (!vector.tryReserveCapacity(length))
449  return false;
450  vector.resize(length);
451 
452  for (int32_t i = 0; i < length; ++i) {
453  JSC::JSValue v = object->get(exec, i);
454  if (exec->hadException())
455  return false;
456  vector[i] = static_cast<T>(v.toNumber(exec));
457  }
458 
459  return true;
460 }
461 
462 enum DataFunctionToCall {
463  f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
464  f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
465 };
466 
467 enum DataFunctionMatrixToCall {
468  f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
469 };
470 
471 static bool functionForUniform(DataFunctionToCall f)
472 {
473  switch (f) {
474  case f_uniform1v:
475  case f_uniform2v:
476  case f_uniform3v:
477  case f_uniform4v:
478  return true;
479  default: break;
480  }
481  return false;
482 }
483 
484 static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
485 {
486  if (exec->argumentCount() != 2)
487  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
488 
489  WebGLUniformLocation* location = 0;
490  long index = -1;
491 
492  if (functionForUniform(f)) {
493  location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
494  if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
495  return throwTypeError(exec);
496  } else
497  index = exec->uncheckedArgument(0).toInt32(exec);
498 
499  if (exec->hadException())
500  return jsUndefined();
501 
502  RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1));
503  if (exec->hadException())
504  return jsUndefined();
505 
506  ExceptionCode ec = 0;
507  if (webGLArray) {
508  switch (f) {
509  case f_uniform1v:
510  context.uniform1fv(location, webGLArray.get(), ec);
511  break;
512  case f_uniform2v:
513  context.uniform2fv(location, webGLArray.get(), ec);
514  break;
515  case f_uniform3v:
516  context.uniform3fv(location, webGLArray.get(), ec);
517  break;
518  case f_uniform4v:
519  context.uniform4fv(location, webGLArray.get(), ec);
520  break;
521  case f_vertexAttrib1v:
522  context.vertexAttrib1fv(index, webGLArray.get());
523  break;
524  case f_vertexAttrib2v:
525  context.vertexAttrib2fv(index, webGLArray.get());
526  break;
527  case f_vertexAttrib3v:
528  context.vertexAttrib3fv(index, webGLArray.get());
529  break;
530  case f_vertexAttrib4v:
531  context.vertexAttrib4fv(index, webGLArray.get());
532  break;
533  }
534 
535  setDOMException(exec, ec);
536  return jsUndefined();
537  }
538 
539  Vector<float, 64> array;
540  if (!toVector(exec, exec->uncheckedArgument(1), array))
541  return throwTypeError(exec);
542 
543  switch (f) {
544  case f_uniform1v:
545  context.uniform1fv(location, array.data(), array.size(), ec);
546  break;
547  case f_uniform2v:
548  context.uniform2fv(location, array.data(), array.size(), ec);
549  break;
550  case f_uniform3v:
551  context.uniform3fv(location, array.data(), array.size(), ec);
552  break;
553  case f_uniform4v:
554  context.uniform4fv(location, array.data(), array.size(), ec);
555  break;
556  case f_vertexAttrib1v:
557  context.vertexAttrib1fv(index, array.data(), array.size());
558  break;
559  case f_vertexAttrib2v:
560  context.vertexAttrib2fv(index, array.data(), array.size());
561  break;
562  case f_vertexAttrib3v:
563  context.vertexAttrib3fv(index, array.data(), array.size());
564  break;
565  case f_vertexAttrib4v:
566  context.vertexAttrib4fv(index, array.data(), array.size());
567  break;
568  }
569 
570  setDOMException(exec, ec);
571  return jsUndefined();
572 }
573 
574 static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
575 {
576  if (exec->argumentCount() != 2)
577  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
578 
579  WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
580  if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
581  return throwTypeError(exec);
582 
583  RefPtr<Int32Array> webGLArray = toInt32Array(exec->uncheckedArgument(1));
584 
585  ExceptionCode ec = 0;
586  if (webGLArray) {
587  switch (f) {
588  case f_uniform1v:
589  context.uniform1iv(location, webGLArray.get(), ec);
590  break;
591  case f_uniform2v:
592  context.uniform2iv(location, webGLArray.get(), ec);
593  break;
594  case f_uniform3v:
595  context.uniform3iv(location, webGLArray.get(), ec);
596  break;
597  case f_uniform4v:
598  context.uniform4iv(location, webGLArray.get(), ec);
599  break;
600  default:
601  break;
602  }
603 
604  setDOMException(exec, ec);
605  return jsUndefined();
606  }
607 
608 
609  Vector<int, 64> array;
610  if (!toVector(exec, exec->uncheckedArgument(1), array))
611  return throwTypeError(exec);
612 
613  switch (f) {
614  case f_uniform1v:
615  context.uniform1iv(location, array.data(), array.size(), ec);
616  break;
617  case f_uniform2v:
618  context.uniform2iv(location, array.data(), array.size(), ec);
619  break;
620  case f_uniform3v:
621  context.uniform3iv(location, array.data(), array.size(), ec);
622  break;
623  case f_uniform4v:
624  context.uniform4iv(location, array.data(), array.size(), ec);
625  break;
626  default:
627  break;
628  }
629 
630  setDOMException(exec, ec);
631  return jsUndefined();
632 }
633 
634 static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
635 {
636  if (exec->argumentCount() != 3)
637  return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
638 
639  WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
640  if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
641  return throwTypeError(exec);
642 
643  bool transpose = exec->uncheckedArgument(1).toBoolean(exec);
644  if (exec->hadException())
645  return jsUndefined();
646 
647  RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(2));
648 
649  ExceptionCode ec = 0;
650  if (webGLArray) {
651  switch (f) {
652  case f_uniformMatrix2fv:
653  context.uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
654  break;
655  case f_uniformMatrix3fv:
656  context.uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
657  break;
658  case f_uniformMatrix4fv:
659  context.uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
660  break;
661  }
662 
663  setDOMException(exec, ec);
664  return jsUndefined();
665  }
666 
667  Vector<float, 64> array;
668  if (!toVector(exec, exec->uncheckedArgument(2), array))
669  return throwTypeError(exec);
670 
671  switch (f) {
672  case f_uniformMatrix2fv:
673  context.uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
674  break;
675  case f_uniformMatrix3fv:
676  context.uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
677  break;
678  case f_uniformMatrix4fv:
679  context.uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
680  break;
681  }
682 
683  setDOMException(exec, ec);
684  return jsUndefined();
685 }
686 
687 JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec)
688 {
689  return dataFunctionf(f_uniform1v, exec, impl());
690 }
691 
692 JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec)
693 {
694  return dataFunctioni(f_uniform1v, exec, impl());
695 }
696 
697 JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec)
698 {
699  return dataFunctionf(f_uniform2v, exec, impl());
700 }
701 
702 JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec)
703 {
704  return dataFunctioni(f_uniform2v, exec, impl());
705 }
706 
707 JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec)
708 {
709  return dataFunctionf(f_uniform3v, exec, impl());
710 }
711 
712 JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec)
713 {
714  return dataFunctioni(f_uniform3v, exec, impl());
715 }
716 
717 JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec)
718 {
719  return dataFunctionf(f_uniform4v, exec, impl());
720 }
721 
722 JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec)
723 {
724  return dataFunctioni(f_uniform4v, exec, impl());
725 }
726 
727 JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec)
728 {
729  return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl());
730 }
731 
732 JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec)
733 {
734  return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl());
735 }
736 
737 JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec)
738 {
739  return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl());
740 }
741 
742 JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec)
743 {
744  return dataFunctionf(f_vertexAttrib1v, exec, impl());
745 }
746 
747 JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec)
748 {
749  return dataFunctionf(f_vertexAttrib2v, exec, impl());
750 }
751 
752 JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec)
753 {
754  return dataFunctionf(f_vertexAttrib3v, exec, impl());
755 }
756 
757 JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec)
758 {
759  return dataFunctionf(f_vertexAttrib4v, exec, impl());
760 }
761 
762 } // namespace WebCore
763 
764 #endif // ENABLE(WEBGL)
178372

Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

@@sub GenerateImplementation
29832983 if (GetGenerateIsReachable($interface) eq "Impl") {
29842984 $rootString = " ${implType}* root = &js${interfaceName}->impl();\n";
29852985 } elsif (GetGenerateIsReachable($interface) eq "ImplWebGLRenderingContext") {
2986  $rootString = " WebGLRenderingContext* root = WTF::getPtr(js${interfaceName}->impl().context());\n";
 2986 $rootString = " WebGLRenderingContextBase* root = WTF::getPtr(js${interfaceName}->impl().context());\n";
29872987 } elsif (GetGenerateIsReachable($interface) eq "ImplFrame") {
29882988 $rootString = " Frame* root = WTF::getPtr(js${interfaceName}->impl().frame());\n";
29892989 $rootString .= " if (!root)\n";
178372

Source/WebCore/html/HTMLCanvasElement.cpp

5252#include <runtime/JSCInlines.h>
5353#include <runtime/JSLock.h>
5454
55 #if ENABLE(WEBGL)
 55#if ENABLE(WEBGL)
 56#include "WebGL1RenderingContext.h"
 57#include "WebGL2RenderingContext.h"
5658#include "WebGLContextAttributes.h"
57 #include "WebGLRenderingContext.h"
5859#endif
5960
6061namespace WebCore {

@@CanvasRenderingContext* HTMLCanvasElemen
212213 if (m_context && !m_context->is3d())
213214 return nullptr;
214215 if (!m_context) {
215  m_context = WebGLRenderingContext::create(this, static_cast<WebGLContextAttributes*>(attrs));
 216 m_context = WebGLRenderingContextBase::create(this, static_cast<WebGLContextAttributes*>(attrs), type);
 217
216218 if (m_context) {
217219 // Need to make sure a RenderLayer and compositing layer get created for the Canvas
218220 setNeedsStyleRecalc(SyntheticStyleChange);

@@bool HTMLCanvasElement::is2dType(const S
255257bool HTMLCanvasElement::is3dType(const String& type)
256258{
257259 // Retain support for the legacy "webkit-3d" name.
258  return type == "webgl" || type == "experimental-webgl" || type == "webkit-3d";
 260 return type == "webgl" || type == "experimental-webgl" || type == "webkit-3d" || type == "experimental-webgl2";
259261}
260262#endif
261263

@@void HTMLCanvasElement::reset()
327329
328330#if ENABLE(WEBGL)
329331 if (is3D() && oldSize != size())
330  static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height());
 332 static_cast<WebGLRenderingContextBase*>(m_context.get())->reshape(width(), height());
331333#endif
332334
333335 if (auto renderer = this->renderer()) {

@@void HTMLCanvasElement::paint(GraphicsCo
394396
395397#if ENABLE(WEBGL)
396398 if (is3D())
397  static_cast<WebGLRenderingContext*>(m_context.get())->markLayerComposited();
 399 static_cast<WebGLRenderingContextBase*>(m_context.get())->markLayerComposited();
398400#endif
399401}
400402

@@RefPtr<ImageData> HTMLCanvasElement::get
475477 if (!is3D())
476478 return nullptr;
477479
478  WebGLRenderingContext* ctx = static_cast<WebGLRenderingContext*>(m_context.get());
 480 WebGLRenderingContextBase* ctx = static_cast<WebGLRenderingContextBase*>(m_context.get());
479481
480482 return ctx->paintRenderingResultsToImageData();
481483#else
178372

Source/WebCore/html/canvas/ANGLEInstancedArrays.cpp

3434
3535namespace WebCore {
3636
37 ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContext* context)
 37ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContextBase* context)
3838 : WebGLExtension(context)
3939{
4040}

@@WebGLExtension::ExtensionName ANGLEInsta
4848 return ANGLEInstancedArraysName;
4949}
5050
51 bool ANGLEInstancedArrays::supported(WebGLRenderingContext* context)
 51bool ANGLEInstancedArrays::supported(WebGLRenderingContextBase* context)
5252{
5353#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
5454 UNUSED_PARAM(context);
178372

Source/WebCore/html/canvas/ANGLEInstancedArrays.h

3030
3131namespace WebCore {
3232
33 class WebGLRenderingContext;
 33class WebGLRenderingContextBase;
3434
3535class ANGLEInstancedArrays final : public WebGLExtension {
3636public:
37  explicit ANGLEInstancedArrays(WebGLRenderingContext*);
 37 explicit ANGLEInstancedArrays(WebGLRenderingContextBase*);
3838 virtual ~ANGLEInstancedArrays();
3939
4040 virtual ExtensionName getName() const;
4141
42  static bool supported(WebGLRenderingContext*);
 42 static bool supported(WebGLRenderingContextBase*);
4343
4444 void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
4545 void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount);
178372

Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp

@@CanvasRenderingContext2D::CanvasRenderin
115115#if !ENABLE(DASHBOARD_SUPPORT)
116116 ASSERT_UNUSED(usesDashboardCompatibilityMode, !usesDashboardCompatibilityMode);
117117#endif
 118 m_type = "2d";
118119}
119120
120121void CanvasRenderingContext2D::unwindStateStack()
178372

Source/WebCore/html/canvas/CanvasRenderingContext.h

@@public:
5454 virtual bool is2d() const { return false; }
5555 virtual bool is3d() const { return false; }
5656 virtual bool isAccelerated() const { return false; }
 57 virtual String type() const { return m_type; }
5758
5859 virtual void paintRenderingResultsToCanvas() {}
5960 virtual PlatformLayer* platformLayer() const { return 0; }

@@protected:
7374 }
7475 void checkOrigin(const URL&);
7576
 77 String m_type;
7678private:
7779 HTMLCanvasElement* m_canvas;
7880};
178372

Source/WebCore/html/canvas/EXTBlendMinMax.cpp

3030
3131namespace WebCore {
3232
33 EXTBlendMinMax::EXTBlendMinMax(WebGLRenderingContext* context)
 33EXTBlendMinMax::EXTBlendMinMax(WebGLRenderingContextBase* context)
3434 : WebGLExtension(context)
3535{
3636}
178372

Source/WebCore/html/canvas/EXTBlendMinMax.h

@@namespace WebCore {
3232
3333class EXTBlendMinMax final : public WebGLExtension {
3434public:
35  explicit EXTBlendMinMax(WebGLRenderingContext*);
 35 explicit EXTBlendMinMax(WebGLRenderingContextBase*);
3636 virtual ~EXTBlendMinMax();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/EXTFragDepth.cpp

3030
3131namespace WebCore {
3232
33 EXTFragDepth::EXTFragDepth(WebGLRenderingContext* context)
 33EXTFragDepth::EXTFragDepth(WebGLRenderingContextBase* context)
3434 : WebGLExtension(context)
3535{
3636}
178372

Source/WebCore/html/canvas/EXTFragDepth.h

@@namespace WebCore {
3232
3333class EXTFragDepth final : public WebGLExtension {
3434public:
35  explicit EXTFragDepth(WebGLRenderingContext*);
 35 explicit EXTFragDepth(WebGLRenderingContextBase*);
3636 virtual ~EXTFragDepth();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/EXTShaderTextureLOD.cpp

3030
3131namespace WebCore {
3232
33 EXTShaderTextureLOD::EXTShaderTextureLOD(WebGLRenderingContext* context)
 33EXTShaderTextureLOD::EXTShaderTextureLOD(WebGLRenderingContextBase* context)
3434 : WebGLExtension(context)
3535{
3636}
178372

Source/WebCore/html/canvas/EXTShaderTextureLOD.h

@@namespace WebCore {
3232
3333class EXTShaderTextureLOD final : public WebGLExtension {
3434public:
35  explicit EXTShaderTextureLOD(WebGLRenderingContext*);
 35 explicit EXTShaderTextureLOD(WebGLRenderingContextBase*);
3636 virtual ~EXTShaderTextureLOD();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.cpp

3131
3232namespace WebCore {
3333
34 EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContext* context)
 34EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContextBase* context)
3535 : WebGLExtension(context)
3636{
3737}
178372

Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.h

@@namespace WebCore {
3232
3333class EXTTextureFilterAnisotropic final : public WebGLExtension {
3434public:
35  explicit EXTTextureFilterAnisotropic(WebGLRenderingContext*);
 35 explicit EXTTextureFilterAnisotropic(WebGLRenderingContextBase*);
3636 virtual ~EXTTextureFilterAnisotropic();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/EXTsRGB.cpp

3030
3131namespace WebCore {
3232
33 EXTsRGB::EXTsRGB(WebGLRenderingContext* context)
 33EXTsRGB::EXTsRGB(WebGLRenderingContextBase* context)
3434 : WebGLExtension(context)
3535{
3636}
178372

Source/WebCore/html/canvas/EXTsRGB.h

@@namespace WebCore {
3232
3333class EXTsRGB final : public WebGLExtension {
3434public:
35  explicit EXTsRGB(WebGLRenderingContext*);
 35 explicit EXTsRGB(WebGLRenderingContextBase*);
3636 virtual ~EXTsRGB();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESElementIndexUint.cpp

3131
3232namespace WebCore {
3333
34 OESElementIndexUint::OESElementIndexUint(WebGLRenderingContext* context)
 34OESElementIndexUint::OESElementIndexUint(WebGLRenderingContextBase* context)
3535 : WebGLExtension(context)
3636{
3737}
178372

Source/WebCore/html/canvas/OESElementIndexUint.h

@@namespace WebCore {
3232
3333class OESElementIndexUint final : public WebGLExtension {
3434public:
35  explicit OESElementIndexUint(WebGLRenderingContext*);
 35 explicit OESElementIndexUint(WebGLRenderingContextBase*);
3636 virtual ~OESElementIndexUint();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESStandardDerivatives.cpp

3131
3232namespace WebCore {
3333
34 OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContext* context)
 34OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContextBase* context)
3535 : WebGLExtension(context)
3636{
3737}
178372

Source/WebCore/html/canvas/OESStandardDerivatives.h

@@namespace WebCore {
3232
3333class OESStandardDerivatives final : public WebGLExtension {
3434public:
35  explicit OESStandardDerivatives(WebGLRenderingContext*);
 35 explicit OESStandardDerivatives(WebGLRenderingContextBase*);
3636 virtual ~OESStandardDerivatives();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESTextureFloat.cpp

3131
3232namespace WebCore {
3333
34 OESTextureFloat::OESTextureFloat(WebGLRenderingContext* context)
 34OESTextureFloat::OESTextureFloat(WebGLRenderingContextBase* context)
3535 : WebGLExtension(context)
3636{
3737}
178372

Source/WebCore/html/canvas/OESTextureFloat.h

@@namespace WebCore {
3232
3333class OESTextureFloat final : public WebGLExtension {
3434public:
35  OESTextureFloat(WebGLRenderingContext*);
 35 OESTextureFloat(WebGLRenderingContextBase*);
3636 virtual ~OESTextureFloat();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESTextureFloatLinear.cpp

3030
3131namespace WebCore {
3232
33 OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContext* context)
 33OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContextBase* context)
3434 : WebGLExtension(context)
3535{
3636}
178372

Source/WebCore/html/canvas/OESTextureFloatLinear.h

@@namespace WebCore {
3232
3333class OESTextureFloatLinear final : public WebGLExtension {
3434public:
35  explicit OESTextureFloatLinear(WebGLRenderingContext*);
 35 explicit OESTextureFloatLinear(WebGLRenderingContextBase*);
3636 virtual ~OESTextureFloatLinear();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESTextureHalfFloat.cpp

3131
3232namespace WebCore {
3333
34 OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContext* context)
 34OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContextBase* context)
3535 : WebGLExtension(context)
3636{
3737}
178372

Source/WebCore/html/canvas/OESTextureHalfFloat.h

@@namespace WebCore {
3232
3333class OESTextureHalfFloat final : public WebGLExtension {
3434public:
35  OESTextureHalfFloat(WebGLRenderingContext*);
 35 OESTextureHalfFloat(WebGLRenderingContextBase*);
3636 virtual ~OESTextureHalfFloat();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESTextureHalfFloatLinear.cpp

3030
3131namespace WebCore {
3232
33 OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContext* context)
 33OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContextBase* context)
3434 : WebGLExtension(context)
3535{
3636}
178372

Source/WebCore/html/canvas/OESTextureHalfFloatLinear.h

@@namespace WebCore {
3232
3333class OESTextureHalfFloatLinear final : public WebGLExtension {
3434public:
35  OESTextureHalfFloatLinear(WebGLRenderingContext*);
 35 OESTextureHalfFloatLinear(WebGLRenderingContextBase*);
3636 virtual ~OESTextureHalfFloatLinear();
3737
3838 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/OESVertexArrayObject.cpp

3333
3434namespace WebCore {
3535
36 OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContext* context)
 36OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContextBase* context)
3737 : WebGLExtension(context)
3838{
3939}
178372

Source/WebCore/html/canvas/OESVertexArrayObject.h

3131
3232namespace WebCore {
3333
34 class WebGLRenderingContext;
 34class WebGLRenderingContextBase;
3535class WebGLVertexArrayObjectOES;
3636
3737typedef int ExceptionCode;
3838
3939class OESVertexArrayObject final : public WebGLExtension {
4040public:
41  OESVertexArrayObject(WebGLRenderingContext*);
 41 OESVertexArrayObject(WebGLRenderingContextBase*);
4242 virtual ~OESVertexArrayObject();
4343
4444 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/WebGL1RenderingContext.cpp

 1/*
 2 * Copyright (C) 2009, 2013, 2014 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEBGL)
 29
 30#include "WebGLRenderingContext.h"
 31
 32#include "ANGLEInstancedArrays.h"
 33#include "CachedImage.h"
 34#include "DOMWindow.h"
 35#include "Document.h"
 36#include "EXTBlendMinMax.h"
 37#include "EXTFragDepth.h"
 38#include "EXTShaderTextureLOD.h"
 39#include "EXTTextureFilterAnisotropic.h"
 40#include "EXTsRGB.h"
 41#include "ExceptionCode.h"
 42#include "Extensions3D.h"
 43#include "Frame.h"
 44#include "FrameLoader.h"
 45#include "FrameLoaderClient.h"
 46#include "FrameView.h"
 47#include "GraphicsContext.h"
 48#include "HTMLCanvasElement.h"
 49#include "HTMLImageElement.h"
 50#include "HTMLVideoElement.h"
 51#include "ImageBuffer.h"
 52#include "ImageData.h"
 53#include "IntSize.h"
 54#include "Logging.h"
 55#include "MainFrame.h"
 56#include "NotImplemented.h"
 57#include "OESElementIndexUint.h"
 58#include "OESStandardDerivatives.h"
 59#include "OESTextureFloat.h"
 60#include "OESTextureFloatLinear.h"
 61#include "OESTextureHalfFloat.h"
 62#include "OESTextureHalfFloatLinear.h"
 63#include "OESVertexArrayObject.h"
 64#include "Page.h"
 65#include "RenderBox.h"
 66#include "Settings.h"
 67#include "WebGLActiveInfo.h"
 68#include "WebGLBuffer.h"
 69#include "WebGLCompressedTextureATC.h"
 70#include "WebGLCompressedTexturePVRTC.h"
 71#include "WebGLCompressedTextureS3TC.h"
 72#include "WebGLContextAttributes.h"
 73#include "WebGLContextEvent.h"
 74#include "WebGLContextGroup.h"
 75#include "WebGLDebugRendererInfo.h"
 76#include "WebGLDebugShaders.h"
 77#include "WebGLDepthTexture.h"
 78#include "WebGLDrawBuffers.h"
 79#include "WebGLFramebuffer.h"
 80#include "WebGLLoseContext.h"
 81#include "WebGLProgram.h"
 82#include "WebGLRenderbuffer.h"
 83#include "WebGLShader.h"
 84#include "WebGLShaderPrecisionFormat.h"
 85#include "WebGLTexture.h"
 86#include "WebGLUniformLocation.h"
 87
 88#include <runtime/JSCInlines.h>
 89#include <runtime/TypedArrayInlines.h>
 90#include <runtime/Uint32Array.h>
 91#include <wtf/StdLibExtras.h>
 92#include <wtf/text/CString.h>
 93#include <wtf/text/StringBuilder.h>
 94
 95namespace WebCore {
 96
 97const double secondsBetweenRestoreAttempts = 1.0;
 98const int maxGLErrorsAllowedToConsole = 256;
 99
 100namespace {
 101
 102 class ScopedDrawingBufferBinder {
 103 public:
 104 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
 105 : m_drawingBuffer(drawingBuffer)
 106 , m_framebufferBinding(framebufferBinding)
 107 {
 108 // Commit DrawingBuffer if needed (e.g., for multisampling)
 109 if (!m_framebufferBinding && m_drawingBuffer)
 110 m_drawingBuffer->commit();
 111 }
 112
 113 ~ScopedDrawingBufferBinder()
 114 {
 115 // Restore DrawingBuffer if needed
 116 if (!m_framebufferBinding && m_drawingBuffer)
 117 m_drawingBuffer->bind();
 118 }
 119
 120 private:
 121 DrawingBuffer* m_drawingBuffer;
 122 WebGLFramebuffer* m_framebufferBinding;
 123 };
 124
 125 Platform3DObject objectOrZero(WebGLObject* object)
 126 {
 127 return object ? object->object() : 0;
 128 }
 129
 130 void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
 131 {
 132 ASSERT(clippedStart && clippedRange);
 133 if (start < 0) {
 134 range += start;
 135 start = 0;
 136 }
 137 GC3Dint end = start + range;
 138 if (end > sourceRange)
 139 range -= end - sourceRange;
 140 *clippedStart = start;
 141 *clippedRange = range;
 142 }
 143
 144 // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
 145 bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
 146 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
 147 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
 148 {
 149 ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
 150 clip1D(x, width, sourceWidth, clippedX, clippedWidth);
 151 clip1D(y, height, sourceHeight, clippedY, clippedHeight);
 152 return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
 153 }
 154
 155 GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
 156 {
 157 if (value < min)
 158 value = min;
 159 if (value > max)
 160 value = max;
 161 return value;
 162 }
 163
 164 // Return true if a character belongs to the ASCII subset as defined in
 165 // GLSL ES 1.0 spec section 3.1.
 166 bool validateCharacter(unsigned char c)
 167 {
 168 // Printing characters are valid except " $ ` @ \ ' DEL.
 169 if (c >= 32 && c <= 126
 170 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
 171 return true;
 172 // Horizontal tab, line feed, vertical tab, form feed, carriage return
 173 // are also valid.
 174 if (c >= 9 && c <= 13)
 175 return true;
 176 return false;
 177 }
 178
 179 bool isPrefixReserved(const String& name)
 180 {
 181 if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_"))
 182 return true;
 183 return false;
 184 }
 185
 186 // Strips comments from shader text. This allows non-ASCII characters
 187 // to be used in comments without potentially breaking OpenGL
 188 // implementations not expecting characters outside the GLSL ES set.
 189 class StripComments {
 190 public:
 191 StripComments(const String& str)
 192 : m_parseState(BeginningOfLine)
 193 , m_sourceString(str)
 194 , m_length(str.length())
 195 , m_position(0)
 196 {
 197 parse();
 198 }
 199
 200 String result()
 201 {
 202 return m_builder.toString();
 203 }
 204
 205 private:
 206 bool hasMoreCharacters() const
 207 {
 208 return (m_position < m_length);
 209 }
 210
 211 void parse()
 212 {
 213 while (hasMoreCharacters()) {
 214 process(current());
 215 // process() might advance the position.
 216 if (hasMoreCharacters())
 217 advance();
 218 }
 219 }
 220
 221 void process(UChar);
 222
 223 bool peek(UChar& character) const
 224 {
 225 if (m_position + 1 >= m_length)
 226 return false;
 227 character = m_sourceString[m_position + 1];
 228 return true;
 229 }
 230
 231 UChar current() const
 232 {
 233 ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length);
 234 return m_sourceString[m_position];
 235 }
 236
 237 void advance()
 238 {
 239 ++m_position;
 240 }
 241
 242 bool isNewline(UChar character) const
 243 {
 244 // Don't attempt to canonicalize newline related characters.
 245 return (character == '\n' || character == '\r');
 246 }
 247
 248 void emit(UChar character)
 249 {
 250 m_builder.append(character);
 251 }
 252
 253 enum ParseState {
 254 // Have not seen an ASCII non-whitespace character yet on
 255 // this line. Possible that we might see a preprocessor
 256 // directive.
 257 BeginningOfLine,
 258
 259 // Have seen at least one ASCII non-whitespace character
 260 // on this line.
 261 MiddleOfLine,
 262
 263 // Handling a preprocessor directive. Passes through all
 264 // characters up to the end of the line. Disables comment
 265 // processing.
 266 InPreprocessorDirective,
 267
 268 // Handling a single-line comment. The comment text is
 269 // replaced with a single space.
 270 InSingleLineComment,
 271
 272 // Handling a multi-line comment. Newlines are passed
 273 // through to preserve line numbers.
 274 InMultiLineComment
 275 };
 276
 277 ParseState m_parseState;
 278 String m_sourceString;
 279 unsigned m_length;
 280 unsigned m_position;
 281 StringBuilder m_builder;
 282 };
 283
 284 void StripComments::process(UChar c)
 285 {
 286 if (isNewline(c)) {
 287 // No matter what state we are in, pass through newlines
 288 // so we preserve line numbers.
 289 emit(c);
 290
 291 if (m_parseState != InMultiLineComment)
 292 m_parseState = BeginningOfLine;
 293
 294 return;
 295 }
 296
 297 UChar temp = 0;
 298 switch (m_parseState) {
 299 case BeginningOfLine:
 300 if (WTF::isASCIISpace(c)) {
 301 emit(c);
 302 break;
 303 }
 304
 305 if (c == '#') {
 306 m_parseState = InPreprocessorDirective;
 307 emit(c);
 308 break;
 309 }
 310
 311 // Transition to normal state and re-handle character.
 312 m_parseState = MiddleOfLine;
 313 process(c);
 314 break;
 315
 316 case MiddleOfLine:
 317 if (c == '/' && peek(temp)) {
 318 if (temp == '/') {
 319 m_parseState = InSingleLineComment;
 320 emit(' ');
 321 advance();
 322 break;
 323 }
 324
 325 if (temp == '*') {
 326 m_parseState = InMultiLineComment;
 327 // Emit the comment start in case the user has
 328 // an unclosed comment and we want to later
 329 // signal an error.
 330 emit('/');
 331 emit('*');
 332 advance();
 333 break;
 334 }
 335 }
 336
 337 emit(c);
 338 break;
 339
 340 case InPreprocessorDirective:
 341 // No matter what the character is, just pass it
 342 // through. Do not parse comments in this state. This
 343 // might not be the right thing to do long term, but it
 344 // should handle the #error preprocessor directive.
 345 emit(c);
 346 break;
 347
 348 case InSingleLineComment:
 349 // The newline code at the top of this function takes care
 350 // of resetting our state when we get out of the
 351 // single-line comment. Swallow all other characters.
 352 break;
 353
 354 case InMultiLineComment:
 355 if (c == '*' && peek(temp) && temp == '/') {
 356 emit('*');
 357 emit('/');
 358 m_parseState = MiddleOfLine;
 359 advance();
 360 break;
 361 }
 362
 363 // Swallow all other characters. Unclear whether we may
 364 // want or need to just emit a space per character to try
 365 // to preserve column numbers for debugging purposes.
 366 break;
 367 }
 368 }
 369} // namespace anonymous
 370
 371class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
 372 WTF_MAKE_FAST_ALLOCATED;
 373public:
 374 explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { }
 375 virtual void onContextLost() override { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); }
 376 virtual ~WebGLRenderingContextLostCallback() {}
 377private:
 378 WebGLRenderingContext* m_context;
 379};
 380
 381class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback {
 382 WTF_MAKE_FAST_ALLOCATED;
 383public:
 384 explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb) : m_context(cb) { }
 385 virtual void onErrorMessage(const String& message, GC3Dint) override
 386 {
 387 if (m_context->m_synthesizedErrorsToConsole)
 388 m_context->printGLErrorToConsole(message);
 389 }
 390 virtual ~WebGLRenderingContextErrorMessageCallback() { }
 391private:
 392 WebGLRenderingContext* m_context;
 393};
 394
 395std::unique_ptr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
 396{
 397 Document& document = canvas->document();
 398 Frame* frame = document.frame();
 399 if (!frame)
 400 return nullptr;
 401
 402 // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in
 403 // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension.
 404 if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) {
 405 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context."));
 406 return nullptr;
 407 }
 408
 409 bool isPendingPolicyResolution = false;
 410 Document& topDocument = document.topDocument();
 411 Page* page = topDocument.page();
 412 if (page && !topDocument.url().isLocalFile()) {
 413 WebGLLoadPolicy policy = page->mainFrame().loader().client().webGLPolicyForURL(topDocument.url());
 414
 415 if (policy == WebGLBlockCreation) {
 416 LOG(WebGL, "The policy for this URL (%s) is to block WebGL.", topDocument.url().host().utf8().data());
 417 return nullptr;
 418 }
 419
 420 if (policy == WebGLPendingCreation) {
 421 LOG(WebGL, "WebGL policy is pending. May need to be resolved later.");
 422 isPendingPolicyResolution = true;
 423 }
 424 }
 425
 426 GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
 427
 428 if (attributes.antialias) {
 429 if (!frame->settings().openGLMultisamplingEnabled())
 430 attributes.antialias = false;
 431 }
 432
 433 attributes.noExtensions = true;
 434 attributes.shareResources = false;
 435 attributes.preferDiscreteGPU = true;
 436
 437 if (frame->settings().forceSoftwareWebGLRendering())
 438 attributes.forceSoftwareRenderer = true;
 439
 440 if (page)
 441 attributes.devicePixelRatio = page->deviceScaleFactor();
 442
 443 if (isPendingPolicyResolution) {
 444 LOG(WebGL, "Create a WebGL context that looks real, but will require a policy resolution if used.");
 445 std::unique_ptr<WebGLRenderingContext> renderingContext(new WebGLRenderingContext(canvas, attributes));
 446 renderingContext->suspendIfNeeded();
 447 return renderingContext;
 448 }
 449
 450 HostWindow* hostWindow = document.view()->root()->hostWindow();
 451 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
 452
 453 if (!context || !context->makeContextCurrent()) {
 454 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
 455 return nullptr;
 456 }
 457
 458 Extensions3D* extensions = context->getExtensions();
 459 if (extensions->supports("GL_EXT_debug_marker"))
 460 extensions->pushGroupMarkerEXT("WebGLRenderingContext");
 461
 462 std::unique_ptr<WebGLRenderingContext> renderingContext(new WebGLRenderingContext(canvas, context, attributes));
 463 renderingContext->suspendIfNeeded();
 464
 465 return renderingContext;
 466}
 467
 468WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
 469 : CanvasRenderingContext(passedCanvas)
 470 , ActiveDOMObject(&passedCanvas->document())
 471 , m_context(0)
 472 , m_drawingBuffer(0)
 473 , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContext::dispatchContextLostEvent)
 474 , m_restoreAllowed(false)
 475 , m_restoreTimer(*this, &WebGLRenderingContext::maybeRestoreContext)
 476 , m_generatedImageCache(0)
 477 , m_contextLost(false)
 478 , m_contextLostMode(SyntheticLostContext)
 479 , m_attributes(attributes)
 480 , m_synthesizedErrorsToConsole(true)
 481 , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
 482 , m_isPendingPolicyResolution(true)
 483 , m_hasRequestedPolicyResolution(false)
 484{
 485}
 486
 487WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
 488 GraphicsContext3D::Attributes attributes)
 489 : CanvasRenderingContext(passedCanvas)
 490 , ActiveDOMObject(&passedCanvas->document())
 491 , m_context(context)
 492 , m_drawingBuffer(0)
 493 , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContext::dispatchContextLostEvent)
 494 , m_restoreAllowed(false)
 495 , m_restoreTimer(*this, &WebGLRenderingContext::maybeRestoreContext)
 496 , m_generatedImageCache(4)
 497 , m_contextLost(false)
 498 , m_contextLostMode(SyntheticLostContext)
 499 , m_attributes(attributes)
 500 , m_synthesizedErrorsToConsole(true)
 501 , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
 502 , m_isPendingPolicyResolution(false)
 503 , m_hasRequestedPolicyResolution(false)
 504{
 505 ASSERT(m_context);
 506 m_contextGroup = WebGLContextGroup::create();
 507 m_contextGroup->addContext(this);
 508
 509 m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
 510 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
 511
 512 if (m_drawingBuffer)
 513 m_drawingBuffer->bind();
 514
 515 setupFlags();
 516 initializeNewContext();
 517}
 518
 519void WebGLRenderingContext::initializeNewContext()
 520{
 521 ASSERT(!m_contextLost);
 522 m_needsUpdate = true;
 523 m_markedCanvasDirty = false;
 524 m_activeTextureUnit = 0;
 525 m_packAlignment = 4;
 526 m_unpackAlignment = 4;
 527 m_unpackFlipY = false;
 528 m_unpackPremultiplyAlpha = false;
 529 m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
 530 m_boundArrayBuffer = 0;
 531 m_currentProgram = 0;
 532 m_framebufferBinding = 0;
 533 m_renderbufferBinding = 0;
 534 m_depthMask = true;
 535 m_stencilEnabled = false;
 536 m_stencilMask = 0xFFFFFFFF;
 537 m_stencilMaskBack = 0xFFFFFFFF;
 538 m_stencilFuncRef = 0;
 539 m_stencilFuncRefBack = 0;
 540 m_stencilFuncMask = 0xFFFFFFFF;
 541 m_stencilFuncMaskBack = 0xFFFFFFFF;
 542 m_layerCleared = false;
 543 m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
 544
 545 m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
 546 m_scissorEnabled = false;
 547 m_clearDepth = 1;
 548 m_clearStencil = 0;
 549 m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
 550
 551 GC3Dint numCombinedTextureImageUnits = 0;
 552 m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
 553 m_textureUnits.clear();
 554 m_textureUnits.resize(numCombinedTextureImageUnits);
 555
 556 GC3Dint numVertexAttribs = 0;
 557 m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
 558 m_maxVertexAttribs = numVertexAttribs;
 559
 560 m_maxTextureSize = 0;
 561 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
 562 m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
 563 m_maxCubeMapTextureSize = 0;
 564 m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
 565 m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
 566 m_maxRenderbufferSize = 0;
 567 m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
 568
 569 // These two values from EXT_draw_buffers are lazily queried.
 570 m_maxDrawBuffers = 0;
 571 m_maxColorAttachments = 0;
 572
 573 m_backDrawBuffer = GraphicsContext3D::BACK;
 574 m_drawBuffersWebGLRequirementsChecked = false;
 575 m_drawBuffersSupported = false;
 576
 577 m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
 578 addContextObject(m_defaultVertexArrayObject.get());
 579 m_boundVertexArrayObject = m_defaultVertexArrayObject;
 580
 581 m_vertexAttribValue.resize(m_maxVertexAttribs);
 582
 583 if (!isGLES2NPOTStrict())
 584 createFallbackBlackTextures1x1();
 585 if (!isGLES2Compliant())
 586 initVertexAttrib0();
 587
 588 IntSize canvasSize = clampedCanvasSize();
 589 if (m_drawingBuffer)
 590 m_drawingBuffer->reset(canvasSize);
 591
 592 m_context->reshape(canvasSize.width(), canvasSize.height());
 593 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
 594 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
 595
 596 m_context->setContextLostCallback(std::make_unique<WebGLRenderingContextLostCallback>(this));
 597 m_context->setErrorMessageCallback(std::make_unique<WebGLRenderingContextErrorMessageCallback>(this));
 598}
 599
 600void WebGLRenderingContext::setupFlags()
 601{
 602 ASSERT(m_context);
 603
 604 if (Page* page = canvas()->document().page())
 605 m_synthesizedErrorsToConsole = page->settings().webGLErrorsToConsoleEnabled();
 606
 607 m_isGLES2Compliant = m_context->isGLES2Compliant();
 608 m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
 609 m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
 610 if (m_isGLES2Compliant) {
 611 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
 612 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
 613 } else {
 614 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
 615 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
 616 }
 617 m_isRobustnessEXTSupported = m_context->getExtensions()->isEnabled("GL_EXT_robustness");
 618}
 619
 620bool WebGLRenderingContext::allowPrivilegedExtensions() const
 621{
 622 if (Page* page = canvas()->document().page())
 623 return page->settings().privilegedWebGLExtensionsEnabled();
 624 return false;
 625}
 626
 627void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format)
 628{
 629 if (!m_compressedTextureFormats.contains(format))
 630 m_compressedTextureFormats.append(format);
 631}
 632
 633WebGLRenderingContext::~WebGLRenderingContext()
 634{
 635 // Remove all references to WebGLObjects so if they are the last reference
 636 // they will be freed before the last context is removed from the context group.
 637 m_boundArrayBuffer = nullptr;
 638 m_defaultVertexArrayObject = nullptr;
 639 m_boundVertexArrayObject = nullptr;
 640 m_vertexAttrib0Buffer = nullptr;
 641 m_currentProgram = nullptr;
 642 m_framebufferBinding = nullptr;
 643 m_renderbufferBinding = nullptr;
 644
 645 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
 646 m_textureUnits[i].texture2DBinding = nullptr;
 647 m_textureUnits[i].textureCubeMapBinding = nullptr;
 648 }
 649
 650 m_blackTexture2D = nullptr;
 651 m_blackTextureCubeMap = nullptr;
 652
 653 if (!m_isPendingPolicyResolution) {
 654 detachAndRemoveAllObjects();
 655 destroyGraphicsContext3D();
 656 m_contextGroup->removeContext(this);
 657 }
 658}
 659
 660void WebGLRenderingContext::destroyGraphicsContext3D()
 661{
 662 if (m_isPendingPolicyResolution)
 663 return;
 664
 665 // The drawing buffer holds a context reference. It must also be destroyed
 666 // in order for the context to be released.
 667 if (m_drawingBuffer)
 668 m_drawingBuffer.clear();
 669
 670 if (m_context) {
 671 m_context->setContextLostCallback(nullptr);
 672 m_context->setErrorMessageCallback(nullptr);
 673 m_context.clear();
 674 }
 675}
 676
 677void WebGLRenderingContext::markContextChanged()
 678{
 679 if (m_framebufferBinding)
 680 return;
 681
 682 m_context->markContextChanged();
 683
 684 if (m_drawingBuffer)
 685 m_drawingBuffer->markContentsChanged();
 686
 687 m_layerCleared = false;
 688 RenderBox* renderBox = canvas()->renderBox();
 689 if (isAccelerated() && renderBox && renderBox->hasAcceleratedCompositing()) {
 690 m_markedCanvasDirty = true;
 691 canvas()->clearCopiedImage();
 692 renderBox->contentChanged(CanvasChanged);
 693 } else {
 694 if (!m_markedCanvasDirty) {
 695 m_markedCanvasDirty = true;
 696 canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
 697 }
 698 }
 699}
 700
 701bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
 702{
 703 if (isContextLostOrPending())
 704 return false;
 705
 706 if (!m_context->layerComposited() || m_layerCleared
 707 || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
 708 return false;
 709
 710 RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
 711
 712 // Determine if it's possible to combine the clear the user asked for and this clear.
 713 bool combinedClear = mask && !m_scissorEnabled;
 714
 715 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
 716 if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
 717 m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
 718 m_colorMask[1] ? m_clearColor[1] : 0,
 719 m_colorMask[2] ? m_clearColor[2] : 0,
 720 m_colorMask[3] ? m_clearColor[3] : 0);
 721 else
 722 m_context->clearColor(0, 0, 0, 0);
 723 m_context->colorMask(true, true, true, true);
 724 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
 725 if (contextAttributes->depth()) {
 726 if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
 727 m_context->clearDepth(1.0f);
 728 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
 729 m_context->depthMask(true);
 730 }
 731 if (contextAttributes->stencil()) {
 732 if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
 733 m_context->clearStencil(m_clearStencil & m_stencilMask);
 734 else
 735 m_context->clearStencil(0);
 736 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
 737 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
 738 }
 739 if (m_drawingBuffer)
 740 m_drawingBuffer->clearFramebuffers(clearMask);
 741 else {
 742 if (m_framebufferBinding)
 743 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
 744 m_context->clear(clearMask);
 745 }
 746
 747 restoreStateAfterClear();
 748 if (m_framebufferBinding)
 749 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 750 m_layerCleared = true;
 751
 752 return combinedClear;
 753}
 754
 755void WebGLRenderingContext::restoreStateAfterClear()
 756{
 757 // Restore the state that the context set.
 758 if (m_scissorEnabled)
 759 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
 760 m_context->clearColor(m_clearColor[0], m_clearColor[1],
 761 m_clearColor[2], m_clearColor[3]);
 762 m_context->colorMask(m_colorMask[0], m_colorMask[1],
 763 m_colorMask[2], m_colorMask[3]);
 764 m_context->clearDepth(m_clearDepth);
 765 m_context->clearStencil(m_clearStencil);
 766 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
 767 m_context->depthMask(m_depthMask);
 768}
 769
 770void WebGLRenderingContext::markLayerComposited()
 771{
 772 if (isContextLostOrPending())
 773 return;
 774 m_context->markLayerComposited();
 775}
 776
 777void WebGLRenderingContext::paintRenderingResultsToCanvas()
 778{
 779 if (isContextLostOrPending())
 780 return;
 781
 782 if (canvas()->document().printing())
 783 canvas()->clearPresentationCopy();
 784
 785 // Until the canvas is written to by the application, the clear that
 786 // happened after it was composited should be ignored by the compositor.
 787 if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
 788 m_context->paintCompositedResultsToCanvas(canvas()->buffer());
 789
 790 canvas()->makePresentationCopy();
 791 } else
 792 canvas()->clearPresentationCopy();
 793 clearIfComposited();
 794
 795 if (!m_markedCanvasDirty && !m_layerCleared)
 796 return;
 797
 798 canvas()->clearCopiedImage();
 799 m_markedCanvasDirty = false;
 800
 801 if (m_drawingBuffer)
 802 m_drawingBuffer->commit();
 803 m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get());
 804
 805 if (m_drawingBuffer) {
 806 if (m_framebufferBinding)
 807 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 808 else
 809 m_drawingBuffer->bind();
 810 }
 811}
 812
 813PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
 814{
 815 if (isContextLostOrPending())
 816 return nullptr;
 817 clearIfComposited();
 818 if (m_drawingBuffer)
 819 m_drawingBuffer->commit();
 820 RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
 821
 822 if (m_drawingBuffer) {
 823 if (m_framebufferBinding)
 824 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 825 else
 826 m_drawingBuffer->bind();
 827 }
 828
 829 return imageData;
 830}
 831
 832void WebGLRenderingContext::reshape(int width, int height)
 833{
 834 if (isContextLostOrPending())
 835 return;
 836
 837 // This is an approximation because at WebGLRenderingContext level we don't
 838 // know if the underlying FBO uses textures or renderbuffers.
 839 GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
 840 // Limit drawing buffer size to 4k to avoid memory exhaustion.
 841 const int sizeUpperLimit = 4096;
 842 maxSize = std::min(maxSize, sizeUpperLimit);
 843 GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
 844 GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
 845 width = clamp(width, 1, maxWidth);
 846 height = clamp(height, 1, maxHeight);
 847
 848 if (m_needsUpdate) {
 849 RenderBox* renderBox = canvas()->renderBox();
 850 if (renderBox && renderBox->hasAcceleratedCompositing())
 851 renderBox->contentChanged(CanvasChanged);
 852 m_needsUpdate = false;
 853 }
 854
 855 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
 856 // clear (and this matches what reshape will do).
 857 if (m_drawingBuffer) {
 858 m_drawingBuffer->reset(IntSize(width, height));
 859 restoreStateAfterClear();
 860 } else
 861 m_context->reshape(width, height);
 862
 863 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].texture2DBinding.get()));
 864 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get()));
 865 if (m_framebufferBinding)
 866 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 867}
 868
 869int WebGLRenderingContext::drawingBufferWidth() const
 870{
 871 if (m_drawingBuffer)
 872 return m_drawingBuffer->size().width();
 873
 874 return m_context->getInternalFramebufferSize().width();
 875}
 876
 877int WebGLRenderingContext::drawingBufferHeight() const
 878{
 879 if (m_drawingBuffer)
 880 return m_drawingBuffer->size().height();
 881
 882 return m_context->getInternalFramebufferSize().height();
 883}
 884
 885unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
 886{
 887 switch (type) {
 888 case GraphicsContext3D::BYTE:
 889 return sizeof(GC3Dbyte);
 890 case GraphicsContext3D::UNSIGNED_BYTE:
 891 return sizeof(GC3Dubyte);
 892 case GraphicsContext3D::SHORT:
 893 return sizeof(GC3Dshort);
 894 case GraphicsContext3D::UNSIGNED_SHORT:
 895 return sizeof(GC3Dushort);
 896 case GraphicsContext3D::INT:
 897 return sizeof(GC3Dint);
 898 case GraphicsContext3D::UNSIGNED_INT:
 899 return sizeof(GC3Duint);
 900 case GraphicsContext3D::FLOAT:
 901 return sizeof(GC3Dfloat);
 902 }
 903 ASSERT_NOT_REACHED();
 904 return 0;
 905}
 906
 907void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
 908{
 909 UNUSED_PARAM(ec);
 910 if (isContextLostOrPending())
 911 return;
 912 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
 913 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range");
 914 return;
 915 }
 916 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
 917 m_context->activeTexture(texture);
 918
 919 if (m_drawingBuffer)
 920 m_drawingBuffer->setActiveTextureUnit(texture);
 921}
 922
 923void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
 924{
 925 UNUSED_PARAM(ec);
 926 if (isContextLostOrPending() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader))
 927 return;
 928 if (!program->attachShader(shader)) {
 929 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
 930 return;
 931 }
 932 m_context->attachShader(objectOrZero(program), objectOrZero(shader));
 933 shader->onAttached();
 934}
 935
 936void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
 937{
 938 UNUSED_PARAM(ec);
 939 if (isContextLostOrPending() || !validateWebGLObject("bindAttribLocation", program))
 940 return;
 941 if (!validateLocationLength("bindAttribLocation", name))
 942 return;
 943 if (!validateString("bindAttribLocation", name))
 944 return;
 945 if (isPrefixReserved(name)) {
 946 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix");
 947 return;
 948 }
 949 if (index >= m_maxVertexAttribs) {
 950 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range");
 951 return;
 952 }
 953 m_context->bindAttribLocation(objectOrZero(program), index, name);
 954}
 955
 956bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted)
 957{
 958 deleted = false;
 959 if (isContextLostOrPending())
 960 return false;
 961 if (object) {
 962 if (!object->validate(contextGroup(), this)) {
 963 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context");
 964 return false;
 965 }
 966 deleted = !object->object();
 967 }
 968 return true;
 969}
 970
 971void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
 972{
 973 UNUSED_PARAM(ec);
 974 bool deleted;
 975 if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
 976 return;
 977 if (deleted)
 978 buffer = 0;
 979 if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
 980 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets");
 981 return;
 982 }
 983 if (target == GraphicsContext3D::ARRAY_BUFFER)
 984 m_boundArrayBuffer = buffer;
 985 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
 986 m_boundVertexArrayObject->setElementArrayBuffer(buffer);
 987 else {
 988 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target");
 989 return;
 990 }
 991
 992 m_context->bindBuffer(target, objectOrZero(buffer));
 993 if (buffer)
 994 buffer->setTarget(target);
 995}
 996
 997void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
 998{
 999 UNUSED_PARAM(ec);
 1000 bool deleted;
 1001 if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
 1002 return;
 1003 if (deleted)
 1004 buffer = 0;
 1005 if (target != GraphicsContext3D::FRAMEBUFFER) {
 1006 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
 1007 return;
 1008 }
 1009 m_framebufferBinding = buffer;
 1010 if (m_drawingBuffer)
 1011 m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get()));
 1012 if (!m_framebufferBinding && m_drawingBuffer) {
 1013 // Instead of binding fb 0, bind the drawing buffer.
 1014 m_drawingBuffer->bind();
 1015 } else
 1016 m_context->bindFramebuffer(target, objectOrZero(buffer));
 1017 if (buffer)
 1018 buffer->setHasEverBeenBound();
 1019 applyStencilTest();
 1020}
 1021
 1022void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
 1023{
 1024 UNUSED_PARAM(ec);
 1025 bool deleted;
 1026 if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
 1027 return;
 1028 if (deleted)
 1029 renderBuffer = 0;
 1030 if (target != GraphicsContext3D::RENDERBUFFER) {
 1031 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target");
 1032 return;
 1033 }
 1034 m_renderbufferBinding = renderBuffer;
 1035 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
 1036 if (renderBuffer)
 1037 renderBuffer->setHasEverBeenBound();
 1038}
 1039
 1040void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
 1041{
 1042 UNUSED_PARAM(ec);
 1043 bool deleted;
 1044 if (!checkObjectToBeBound("bindTexture", texture, deleted))
 1045 return;
 1046 if (deleted)
 1047 texture = 0;
 1048 if (texture && texture->getTarget() && texture->getTarget() != target) {
 1049 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets");
 1050 return;
 1051 }
 1052 GC3Dint maxLevel = 0;
 1053 if (target == GraphicsContext3D::TEXTURE_2D) {
 1054 m_textureUnits[m_activeTextureUnit].texture2DBinding = texture;
 1055 maxLevel = m_maxTextureLevel;
 1056
 1057 if (m_drawingBuffer && !m_activeTextureUnit)
 1058 m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
 1059
 1060 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
 1061 m_textureUnits[m_activeTextureUnit].textureCubeMapBinding = texture;
 1062 maxLevel = m_maxCubeMapTextureLevel;
 1063 } else {
 1064 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target");
 1065 return;
 1066 }
 1067 m_context->bindTexture(target, objectOrZero(texture));
 1068 if (texture)
 1069 texture->setTarget(target, maxLevel);
 1070
 1071 // Note: previously we used to automatically set the TEXTURE_WRAP_R
 1072 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
 1073 // ES 2.0 doesn't expose this flag (a bug in the specification) and
 1074 // otherwise the application has no control over the seams in this
 1075 // dimension. However, it appears that supporting this properly on all
 1076 // platforms is fairly involved (will require a HashMap from texture ID
 1077 // in all ports), and we have not had any complaints, so the logic has
 1078 // been removed.
 1079}
 1080
 1081void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
 1082{
 1083 if (isContextLostOrPending())
 1084 return;
 1085 m_context->blendColor(red, green, blue, alpha);
 1086}
 1087
 1088void WebGLRenderingContext::blendEquation(GC3Denum mode)
 1089{
 1090 if (isContextLostOrPending() || !validateBlendEquation("blendEquation", mode))
 1091 return;
 1092 m_context->blendEquation(mode);
 1093}
 1094
 1095void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
 1096{
 1097 if (isContextLostOrPending() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha))
 1098 return;
 1099 m_context->blendEquationSeparate(modeRGB, modeAlpha);
 1100}
 1101
 1102
 1103void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
 1104{
 1105 if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor))
 1106 return;
 1107 m_context->blendFunc(sfactor, dfactor);
 1108}
 1109
 1110void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
 1111{
 1112 // Note: Alpha does not have the same restrictions as RGB.
 1113 if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB))
 1114 return;
 1115 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
 1116}
 1117
 1118void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
 1119{
 1120 UNUSED_PARAM(ec);
 1121 if (isContextLostOrPending())
 1122 return;
 1123 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
 1124 if (!buffer)
 1125 return;
 1126 if (size < 0) {
 1127 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
 1128 return;
 1129 }
 1130 if (!size) {
 1131 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0");
 1132 return;
 1133 }
 1134 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1135 if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
 1136 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
 1137 return;
 1138 }
 1139 }
 1140
 1141 m_context->moveErrorsToSyntheticErrorList();
 1142 m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
 1143 if (m_context->moveErrorsToSyntheticErrorList()) {
 1144 // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1145 buffer->disassociateBufferData();
 1146 }
 1147}
 1148
 1149void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
 1150{
 1151 UNUSED_PARAM(ec);
 1152 if (isContextLostOrPending())
 1153 return;
 1154 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
 1155 if (!buffer)
 1156 return;
 1157 if (!data) {
 1158 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
 1159 return;
 1160 }
 1161 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1162 if (!buffer->associateBufferData(data)) {
 1163 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
 1164 return;
 1165 }
 1166 }
 1167
 1168 m_context->moveErrorsToSyntheticErrorList();
 1169 m_context->bufferData(target, data->byteLength(), data->data(), usage);
 1170 if (m_context->moveErrorsToSyntheticErrorList()) {
 1171 // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1172 buffer->disassociateBufferData();
 1173 }
 1174}
 1175
 1176void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
 1177{
 1178 UNUSED_PARAM(ec);
 1179 if (isContextLostOrPending())
 1180 return;
 1181 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
 1182 if (!buffer)
 1183 return;
 1184 if (!data) {
 1185 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
 1186 return;
 1187 }
 1188 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1189 if (!buffer->associateBufferData(data)) {
 1190 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
 1191 return;
 1192 }
 1193 }
 1194
 1195 m_context->moveErrorsToSyntheticErrorList();
 1196 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
 1197 if (m_context->moveErrorsToSyntheticErrorList()) {
 1198 // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1199 buffer->disassociateBufferData();
 1200 }
 1201}
 1202
 1203void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
 1204{
 1205 UNUSED_PARAM(ec);
 1206 if (isContextLostOrPending())
 1207 return;
 1208 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
 1209 if (!buffer)
 1210 return;
 1211 if (offset < 0) {
 1212 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
 1213 return;
 1214 }
 1215 if (!data)
 1216 return;
 1217 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1218 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
 1219 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
 1220 return;
 1221 }
 1222 }
 1223
 1224 m_context->moveErrorsToSyntheticErrorList();
 1225 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
 1226 if (m_context->moveErrorsToSyntheticErrorList()) {
 1227 // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1228 buffer->disassociateBufferData();
 1229 }
 1230}
 1231
 1232void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
 1233{
 1234 UNUSED_PARAM(ec);
 1235 if (isContextLostOrPending())
 1236 return;
 1237 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
 1238 if (!buffer)
 1239 return;
 1240 if (offset < 0) {
 1241 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
 1242 return;
 1243 }
 1244 if (!data)
 1245 return;
 1246 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1247 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
 1248 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
 1249 return;
 1250 }
 1251 }
 1252
 1253 m_context->moveErrorsToSyntheticErrorList();
 1254 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
 1255 if (m_context->moveErrorsToSyntheticErrorList()) {
 1256 // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1257 buffer->disassociateBufferData();
 1258 }
 1259}
 1260
 1261GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
 1262{
 1263 if (isContextLostOrPending())
 1264 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
 1265 if (target != GraphicsContext3D::FRAMEBUFFER) {
 1266 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
 1267 return 0;
 1268 }
 1269 if (!m_framebufferBinding || !m_framebufferBinding->object())
 1270 return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
 1271 const char* reason = "framebuffer incomplete";
 1272 GC3Denum result = m_framebufferBinding->checkStatus(&reason);
 1273 if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
 1274 printGLWarningToConsole("checkFramebufferStatus", reason);
 1275 return result;
 1276 }
 1277 result = m_context->checkFramebufferStatus(target);
 1278 return result;
 1279}
 1280
 1281void WebGLRenderingContext::clear(GC3Dbitfield mask)
 1282{
 1283 if (isContextLostOrPending())
 1284 return;
 1285 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
 1286 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
 1287 return;
 1288 }
 1289 const char* reason = "framebuffer incomplete";
 1290 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 1291 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
 1292 return;
 1293 }
 1294 if (!clearIfComposited(mask))
 1295 m_context->clear(mask);
 1296 markContextChanged();
 1297}
 1298
 1299void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
 1300{
 1301 if (isContextLostOrPending())
 1302 return;
 1303 if (std::isnan(r))
 1304 r = 0;
 1305 if (std::isnan(g))
 1306 g = 0;
 1307 if (std::isnan(b))
 1308 b = 0;
 1309 if (std::isnan(a))
 1310 a = 1;
 1311 m_clearColor[0] = r;
 1312 m_clearColor[1] = g;
 1313 m_clearColor[2] = b;
 1314 m_clearColor[3] = a;
 1315 m_context->clearColor(r, g, b, a);
 1316}
 1317
 1318void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
 1319{
 1320 if (isContextLostOrPending())
 1321 return;
 1322 m_clearDepth = depth;
 1323 m_context->clearDepth(depth);
 1324}
 1325
 1326void WebGLRenderingContext::clearStencil(GC3Dint s)
 1327{
 1328 if (isContextLostOrPending())
 1329 return;
 1330 m_clearStencil = s;
 1331 m_context->clearStencil(s);
 1332}
 1333
 1334void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
 1335{
 1336 if (isContextLostOrPending())
 1337 return;
 1338 m_colorMask[0] = red;
 1339 m_colorMask[1] = green;
 1340 m_colorMask[2] = blue;
 1341 m_colorMask[3] = alpha;
 1342 m_context->colorMask(red, green, blue, alpha);
 1343}
 1344
 1345void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
 1346{
 1347 UNUSED_PARAM(ec);
 1348 if (isContextLostOrPending() || !validateWebGLObject("compileShader", shader))
 1349 return;
 1350 m_context->compileShader(objectOrZero(shader));
 1351 GC3Dint value;
 1352 m_context->getShaderiv(objectOrZero(shader), GraphicsContext3D::COMPILE_STATUS, &value);
 1353 shader->setValid(value);
 1354}
 1355
 1356void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
 1357 GC3Dsizei height, GC3Dint border, ArrayBufferView* data)
 1358{
 1359 if (isContextLostOrPending())
 1360 return;
 1361 if (!validateTexFuncLevel("compressedTexImage2D", target, level))
 1362 return;
 1363
 1364 if (!validateCompressedTexFormat(internalformat)) {
 1365 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat");
 1366 return;
 1367 }
 1368 if (border) {
 1369 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0");
 1370 return;
 1371 }
 1372 if (!validateCompressedTexDimensions("compressedTexImage2D", target, level, width, height, internalformat))
 1373 return;
 1374 if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data))
 1375 return;
 1376
 1377 WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true);
 1378 if (!tex)
 1379 return;
 1380 if (!isGLES2NPOTStrict()) {
 1381 if (level && WebGLTexture::isNPOT(width, height)) {
 1382 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2");
 1383 return;
 1384 }
 1385 }
 1386 m_context->moveErrorsToSyntheticErrorList();
 1387 m_context->compressedTexImage2D(target, level, internalformat, width, height,
 1388 border, data->byteLength(), data->baseAddress());
 1389 if (m_context->moveErrorsToSyntheticErrorList()) {
 1390 // The compressedTexImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
 1391 tex->markInvalid(target, level);
 1392 return;
 1393 }
 1394
 1395 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
 1396 tex->setCompressed();
 1397}
 1398
 1399void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 1400 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data)
 1401{
 1402 if (isContextLostOrPending())
 1403 return;
 1404 if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
 1405 return;
 1406 if (!validateCompressedTexFormat(format)) {
 1407 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format");
 1408 return;
 1409 }
 1410 if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
 1411 return;
 1412
 1413 WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true);
 1414 if (!tex)
 1415 return;
 1416
 1417 if (format != tex->getInternalFormat(target, level)) {
 1418 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format");
 1419 return;
 1420 }
 1421
 1422 if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex))
 1423 return;
 1424
 1425 graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset,
 1426 width, height, format, data->byteLength(), data->baseAddress());
 1427 tex->setCompressed();
 1428}
 1429
 1430bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format)
 1431{
 1432 if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
 1433 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
 1434 return false;
 1435 }
 1436 return true;
 1437}
 1438
 1439void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
 1440{
 1441 if (isContextLostOrPending())
 1442 return;
 1443 if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
 1444 return;
 1445 if (!validateSettableTexFormat("copyTexImage2D", internalformat))
 1446 return;
 1447 WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
 1448 if (!tex)
 1449 return;
 1450 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
 1451 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
 1452 return;
 1453 }
 1454 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
 1455 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
 1456 return;
 1457 }
 1458 const char* reason = "framebuffer incomplete";
 1459 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 1460 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
 1461 return;
 1462 }
 1463 clearIfComposited();
 1464 if (isResourceSafe()) {
 1465 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1466 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
 1467 } else {
 1468 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1469 GC3Dint clippedX, clippedY;
 1470 GC3Dsizei clippedWidth, clippedHeight;
 1471 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
 1472 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
 1473 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
 1474 if (clippedWidth > 0 && clippedHeight > 0) {
 1475 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
 1476 clippedX, clippedY, clippedWidth, clippedHeight);
 1477 }
 1478 } else
 1479 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
 1480 }
 1481 // FIXME: if the framebuffer is not complete, none of the below should be executed.
 1482 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
 1483}
 1484
 1485void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 1486{
 1487 if (isContextLostOrPending())
 1488 return;
 1489 if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
 1490 return;
 1491 WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true);
 1492 if (!tex)
 1493 return;
 1494 if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height))
 1495 return;
 1496 // Before checking if it is in the range, check if overflow happens first.
 1497 if (xoffset + width < 0 || yoffset + height < 0) {
 1498 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions");
 1499 return;
 1500 }
 1501 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
 1502 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
 1503 return;
 1504 }
 1505 GC3Denum internalformat = tex->getInternalFormat(target, level);
 1506 if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
 1507 return;
 1508 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
 1509 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
 1510 return;
 1511 }
 1512 const char* reason = "framebuffer incomplete";
 1513 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 1514 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
 1515 return;
 1516 }
 1517 clearIfComposited();
 1518 if (isResourceSafe()) {
 1519 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1520 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 1521 } else {
 1522 GC3Dint clippedX, clippedY;
 1523 GC3Dsizei clippedWidth, clippedHeight;
 1524 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
 1525 GC3Denum format = tex->getInternalFormat(target, level);
 1526 GC3Denum type = tex->getType(target, level);
 1527 std::unique_ptr<unsigned char[]> zero;
 1528 if (width && height) {
 1529 unsigned int size;
 1530 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
 1531 if (error != GraphicsContext3D::NO_ERROR) {
 1532 synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
 1533 return;
 1534 }
 1535 zero = std::make_unique<unsigned char[]>(size);
 1536 if (!zero) {
 1537 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory");
 1538 return;
 1539 }
 1540 memset(zero.get(), 0, size);
 1541 }
 1542 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
 1543 if (clippedWidth > 0 && clippedHeight > 0) {
 1544 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1545 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
 1546 clippedX, clippedY, clippedWidth, clippedHeight);
 1547 }
 1548 } else {
 1549 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1550 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 1551 }
 1552 }
 1553}
 1554
 1555PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
 1556{
 1557 if (isContextLostOrPending())
 1558 return nullptr;
 1559 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
 1560 addSharedObject(o.get());
 1561 return o;
 1562}
 1563
 1564PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
 1565{
 1566 if (isContextLostOrPending())
 1567 return nullptr;
 1568 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
 1569 addContextObject(o.get());
 1570 return o;
 1571}
 1572
 1573PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
 1574{
 1575 if (isContextLostOrPending())
 1576 return nullptr;
 1577 RefPtr<WebGLTexture> o = WebGLTexture::create(this);
 1578 addSharedObject(o.get());
 1579 return o;
 1580}
 1581
 1582PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
 1583{
 1584 if (isContextLostOrPending())
 1585 return nullptr;
 1586 RefPtr<WebGLProgram> o = WebGLProgram::create(this);
 1587 addSharedObject(o.get());
 1588 return o;
 1589}
 1590
 1591PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
 1592{
 1593 if (isContextLostOrPending())
 1594 return nullptr;
 1595 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
 1596 addSharedObject(o.get());
 1597 return o;
 1598}
 1599
 1600PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
 1601{
 1602 UNUSED_PARAM(ec);
 1603 if (isContextLostOrPending())
 1604 return nullptr;
 1605 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
 1606 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type");
 1607 return nullptr;
 1608 }
 1609
 1610 RefPtr<WebGLShader> o = WebGLShader::create(this, type);
 1611 addSharedObject(o.get());
 1612 return o;
 1613}
 1614
 1615void WebGLRenderingContext::cullFace(GC3Denum mode)
 1616{
 1617 if (isContextLostOrPending())
 1618 return;
 1619 m_context->cullFace(mode);
 1620}
 1621
 1622bool WebGLRenderingContext::deleteObject(WebGLObject* object)
 1623{
 1624 if (isContextLostOrPending() || !object)
 1625 return false;
 1626 if (!object->validate(contextGroup(), this)) {
 1627 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context");
 1628 return false;
 1629 }
 1630 if (object->object())
 1631 // We need to pass in context here because we want
 1632 // things in this context unbound.
 1633 object->deleteObject(graphicsContext3D());
 1634 return true;
 1635}
 1636
 1637void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
 1638{
 1639 if (!deleteObject(buffer))
 1640 return;
 1641 if (m_boundArrayBuffer == buffer)
 1642 m_boundArrayBuffer = 0;
 1643
 1644 m_boundVertexArrayObject->unbindBuffer(buffer);
 1645}
 1646
 1647void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
 1648{
 1649 if (!deleteObject(framebuffer))
 1650 return;
 1651 if (framebuffer == m_framebufferBinding) {
 1652 m_framebufferBinding = 0;
 1653 if (m_drawingBuffer) {
 1654 m_drawingBuffer->setFramebufferBinding(0);
 1655 // Have to call bindFramebuffer here to bind back to internal fbo.
 1656 m_drawingBuffer->bind();
 1657 } else
 1658 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
 1659 }
 1660}
 1661
 1662void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
 1663{
 1664 deleteObject(program);
 1665 // We don't reset m_currentProgram to 0 here because the deletion of the
 1666 // current program is delayed.
 1667}
 1668
 1669void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
 1670{
 1671 if (!deleteObject(renderbuffer))
 1672 return;
 1673 if (renderbuffer == m_renderbufferBinding)
 1674 m_renderbufferBinding = 0;
 1675 if (m_framebufferBinding)
 1676 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
 1677}
 1678
 1679void WebGLRenderingContext::deleteShader(WebGLShader* shader)
 1680{
 1681 deleteObject(shader);
 1682}
 1683
 1684void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
 1685{
 1686 if (!deleteObject(texture))
 1687 return;
 1688 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
 1689 if (texture == m_textureUnits[i].texture2DBinding)
 1690 m_textureUnits[i].texture2DBinding = nullptr;
 1691 if (texture == m_textureUnits[i].textureCubeMapBinding)
 1692 m_textureUnits[i].textureCubeMapBinding = nullptr;
 1693 }
 1694 if (m_framebufferBinding)
 1695 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
 1696}
 1697
 1698void WebGLRenderingContext::depthFunc(GC3Denum func)
 1699{
 1700 if (isContextLostOrPending())
 1701 return;
 1702 m_context->depthFunc(func);
 1703}
 1704
 1705void WebGLRenderingContext::depthMask(GC3Dboolean flag)
 1706{
 1707 if (isContextLostOrPending())
 1708 return;
 1709 m_depthMask = flag;
 1710 m_context->depthMask(flag);
 1711}
 1712
 1713void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
 1714{
 1715 if (isContextLostOrPending())
 1716 return;
 1717 if (zNear > zFar) {
 1718 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar");
 1719 return;
 1720 }
 1721 m_context->depthRange(zNear, zFar);
 1722}
 1723
 1724void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
 1725{
 1726 UNUSED_PARAM(ec);
 1727 if (isContextLostOrPending() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader))
 1728 return;
 1729 if (!program->detachShader(shader)) {
 1730 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
 1731 return;
 1732 }
 1733 m_context->detachShader(objectOrZero(program), objectOrZero(shader));
 1734 shader->onDetached(graphicsContext3D());
 1735}
 1736
 1737void WebGLRenderingContext::disable(GC3Denum cap)
 1738{
 1739 if (isContextLostOrPending() || !validateCapability("disable", cap))
 1740 return;
 1741 if (cap == GraphicsContext3D::STENCIL_TEST) {
 1742 m_stencilEnabled = false;
 1743 applyStencilTest();
 1744 return;
 1745 }
 1746 if (cap == GraphicsContext3D::SCISSOR_TEST) {
 1747 m_scissorEnabled = false;
 1748 if (m_drawingBuffer)
 1749 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
 1750 }
 1751 m_context->disable(cap);
 1752}
 1753
 1754void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
 1755{
 1756 UNUSED_PARAM(ec);
 1757 if (isContextLostOrPending())
 1758 return;
 1759 if (index >= m_maxVertexAttribs) {
 1760 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range");
 1761 return;
 1762 }
 1763
 1764 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
 1765 state.enabled = false;
 1766
 1767 if (index > 0 || isGLES2Compliant())
 1768 m_context->disableVertexAttribArray(index);
 1769}
 1770
 1771bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
 1772{
 1773 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
 1774
 1775 if (!elementArrayBuffer)
 1776 return false;
 1777
 1778 if (offset < 0)
 1779 return false;
 1780
 1781 if (type == GraphicsContext3D::UNSIGNED_INT) {
 1782 // For an unsigned int array, offset must be divisible by 4 for alignment reasons.
 1783 if (offset % 4)
 1784 return false;
 1785
 1786 // Make uoffset an element offset.
 1787 offset /= 4;
 1788
 1789 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 4;
 1790 if (offset > n || count > n - offset)
 1791 return false;
 1792 } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
 1793 // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
 1794 if (offset % 2)
 1795 return false;
 1796
 1797 // Make uoffset an element offset.
 1798 offset /= 2;
 1799
 1800 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
 1801 if (offset > n || count > n - offset)
 1802 return false;
 1803 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
 1804 GC3Dsizeiptr n = elementArrayBuffer->byteLength();
 1805 if (offset > n || count > n - offset)
 1806 return false;
 1807 }
 1808 return true;
 1809}
 1810
 1811bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
 1812{
 1813 // Performs conservative validation by caching a maximum index of
 1814 // the given type per element array buffer. If all of the bound
 1815 // array buffers have enough elements to satisfy that maximum
 1816 // index, skips the expensive per-draw-call iteration in
 1817 // validateIndexArrayPrecise.
 1818
 1819 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
 1820
 1821 if (!elementArrayBuffer)
 1822 return false;
 1823
 1824 GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
 1825 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
 1826 if (!numElements)
 1827 return false;
 1828 const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
 1829 ASSERT(buffer);
 1830
 1831 int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
 1832 if (maxIndex < 0) {
 1833 // Compute the maximum index in the entire buffer for the given type of index.
 1834 switch (type) {
 1835 case GraphicsContext3D::UNSIGNED_BYTE: {
 1836 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
 1837 for (GC3Dsizeiptr i = 0; i < numElements; i++)
 1838 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
 1839 break;
 1840 }
 1841 case GraphicsContext3D::UNSIGNED_SHORT: {
 1842 numElements /= sizeof(GC3Dushort);
 1843 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
 1844 for (GC3Dsizeiptr i = 0; i < numElements; i++)
 1845 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
 1846 break;
 1847 }
 1848 case GraphicsContext3D::UNSIGNED_INT: {
 1849 if (!m_oesElementIndexUint)
 1850 return false;
 1851 numElements /= sizeof(GC3Duint);
 1852 const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
 1853 for (GC3Dsizeiptr i = 0; i < numElements; i++)
 1854 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
 1855 break;
 1856 }
 1857 default:
 1858 return false;
 1859 }
 1860 elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
 1861 }
 1862
 1863 if (maxIndex >= 0) {
 1864 // The number of required elements is one more than the maximum
 1865 // index that will be accessed.
 1866 numElementsRequired = maxIndex + 1;
 1867 return true;
 1868 }
 1869
 1870 return false;
 1871}
 1872
 1873bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired)
 1874{
 1875 ASSERT(count >= 0 && offset >= 0);
 1876 unsigned lastIndex = 0;
 1877
 1878 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
 1879
 1880 if (!elementArrayBuffer)
 1881 return false;
 1882
 1883 if (!count) {
 1884 numElementsRequired = 0;
 1885 return true;
 1886 }
 1887
 1888 if (!elementArrayBuffer->elementArrayBuffer())
 1889 return false;
 1890
 1891 unsigned long uoffset = offset;
 1892 unsigned long n = count;
 1893
 1894 if (type == GraphicsContext3D::UNSIGNED_INT) {
 1895 // Make uoffset an element offset.
 1896 uoffset /= sizeof(GC3Duint);
 1897 const GC3Duint* p = static_cast<const GC3Duint*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
 1898 while (n-- > 0) {
 1899 if (*p > lastIndex)
 1900 lastIndex = *p;
 1901 ++p;
 1902 }
 1903 } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
 1904 // Make uoffset an element offset.
 1905 uoffset /= sizeof(GC3Dushort);
 1906 const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
 1907 while (n-- > 0) {
 1908 if (*p > lastIndex)
 1909 lastIndex = *p;
 1910 ++p;
 1911 }
 1912 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
 1913 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
 1914 while (n-- > 0) {
 1915 if (*p > lastIndex)
 1916 lastIndex = *p;
 1917 ++p;
 1918 }
 1919 }
 1920
 1921 // Then set the last index in the index array and make sure it is valid.
 1922 numElementsRequired = lastIndex + 1;
 1923 return numElementsRequired > 0;
 1924}
 1925
 1926bool WebGLRenderingContext::validateVertexAttributes(unsigned elementCount, unsigned primitiveCount)
 1927{
 1928 if (!m_currentProgram)
 1929 return false;
 1930
 1931 // Look in each enabled vertex attrib and check if they've been bound to a buffer.
 1932 for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
 1933 if (!m_boundVertexArrayObject->getVertexAttribState(i).validateBinding())
 1934 return false;
 1935 }
 1936
 1937 if (elementCount <= 0)
 1938 return true;
 1939
 1940
 1941 // Look in each consumed vertex attrib (by the current program).
 1942 bool sawNonInstancedAttrib = false;
 1943 bool sawEnabledAttrib = false;
 1944 int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
 1945 for (int i = 0; i < numActiveAttribLocations; ++i) {
 1946 int loc = m_currentProgram->getActiveAttribLocation(i);
 1947 if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
 1948 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
 1949 if (state.enabled) {
 1950 sawEnabledAttrib = true;
 1951 // Avoid off-by-one errors in numElements computation.
 1952 // For the last element, we will only touch the data for the
 1953 // element and nothing beyond it.
 1954 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
 1955 unsigned numElements = 0;
 1956 ASSERT(state.stride > 0);
 1957 if (bytesRemaining >= state.bytesPerElement)
 1958 numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
 1959 unsigned instancesRequired = 0;
 1960 if (state.divisor) {
 1961 instancesRequired = ceil(static_cast<float>(primitiveCount) / state.divisor);
 1962 if (instancesRequired > numElements)
 1963 return false;
 1964 } else {
 1965 sawNonInstancedAttrib = true;
 1966 if (elementCount > numElements)
 1967 return false;
 1968 }
 1969 }
 1970 }
 1971 }
 1972
 1973 if (!sawNonInstancedAttrib && sawEnabledAttrib)
 1974 return false;
 1975
 1976 return true;
 1977}
 1978
 1979bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object)
 1980{
 1981 if (!object || !object->object()) {
 1982 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted");
 1983 return false;
 1984 }
 1985 if (!object->validate(contextGroup(), this)) {
 1986 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context");
 1987 return false;
 1988 }
 1989 return true;
 1990}
 1991
 1992bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primitiveCount)
 1993{
 1994 if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
 1995 return false;
 1996
 1997 if (!validateStencilSettings(functionName))
 1998 return false;
 1999
 2000 if (first < 0 || count < 0) {
 2001 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0");
 2002 return false;
 2003 }
 2004
 2005 if (!count) {
 2006 markContextChanged();
 2007 return false;
 2008 }
 2009
 2010 if (primitiveCount < 0) {
 2011 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
 2012 return false;
 2013 }
 2014
 2015 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 2016 // Ensure we have a valid rendering state
 2017 Checked<GC3Dint, RecordOverflow> checkedFirst(first);
 2018 Checked<GC3Dint, RecordOverflow> checkedCount(count);
 2019 Checked<GC3Dint, RecordOverflow> checkedSum = checkedFirst + checkedCount;
 2020 Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount);
 2021 if (checkedSum.hasOverflowed() || checkedPrimitiveCount.hasOverflowed() || !validateVertexAttributes(checkedSum.unsafeGet(), checkedPrimitiveCount.unsafeGet())) {
 2022 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
 2023 return false;
 2024 }
 2025 } else {
 2026 if (!validateVertexAttributes(0)) {
 2027 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
 2028 return false;
 2029 }
 2030 }
 2031
 2032 const char* reason = "framebuffer incomplete";
 2033 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 2034 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
 2035 return false;
 2036 }
 2037
 2038 return true;
 2039}
 2040
 2041void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
 2042{
 2043 UNUSED_PARAM(ec);
 2044
 2045 if (!validateDrawArrays("drawArrays", mode, first, count, 0))
 2046 return;
 2047
 2048 clearIfComposited();
 2049
 2050 bool vertexAttrib0Simulated = false;
 2051 if (!isGLES2Compliant())
 2052 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
 2053 if (!isGLES2NPOTStrict())
 2054 checkTextureCompleteness("drawArrays", true);
 2055
 2056 m_context->drawArrays(mode, first, count);
 2057
 2058 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 2059 restoreStatesAfterVertexAttrib0Simulation();
 2060 if (!isGLES2NPOTStrict())
 2061 checkTextureCompleteness("drawArrays", false);
 2062 markContextChanged();
 2063}
 2064
 2065bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primitiveCount)
 2066{
 2067 if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
 2068 return false;
 2069
 2070 if (!validateStencilSettings(functionName))
 2071 return false;
 2072
 2073 switch (type) {
 2074 case GraphicsContext3D::UNSIGNED_BYTE:
 2075 case GraphicsContext3D::UNSIGNED_SHORT:
 2076 break;
 2077 case GraphicsContext3D::UNSIGNED_INT:
 2078 if (m_oesElementIndexUint)
 2079 break;
 2080 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
 2081 return false;
 2082 default:
 2083 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
 2084 return false;
 2085 }
 2086
 2087 if (count < 0 || offset < 0) {
 2088 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0");
 2089 return false;
 2090 }
 2091
 2092 if (!count) {
 2093 markContextChanged();
 2094 return false;
 2095 }
 2096
 2097 if (primitiveCount < 0) {
 2098 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
 2099 return false;
 2100 }
 2101
 2102 if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
 2103 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound");
 2104 return false;
 2105 }
 2106
 2107 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 2108 // Ensure we have a valid rendering state
 2109 if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
 2110 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "request out of bounds for current ELEMENT_ARRAY_BUFFER");
 2111 return false;
 2112 }
 2113 if (!count)
 2114 return false;
 2115
 2116 Checked<GC3Dint, RecordOverflow> checkedCount(count);
 2117 Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount);
 2118 if (checkedCount.hasOverflowed() || checkedPrimitiveCount.hasOverflowed()) {
 2119 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
 2120 return false;
 2121 }
 2122
 2123 if (!validateIndexArrayConservative(type, numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) {
 2124 if (!validateIndexArrayPrecise(checkedCount.unsafeGet(), type, static_cast<GC3Dintptr>(offset), numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) {
 2125 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
 2126 return false;
 2127 }
 2128 }
 2129 } else {
 2130 if (!validateVertexAttributes(0)) {
 2131 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
 2132 return false;
 2133 }
 2134 }
 2135
 2136 const char* reason = "framebuffer incomplete";
 2137 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 2138 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
 2139 return false;
 2140 }
 2141
 2142 return true;
 2143}
 2144
 2145void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
 2146{
 2147 UNUSED_PARAM(ec);
 2148
 2149 unsigned numElements = 0;
 2150 if (!validateDrawElements("drawElements", mode, count, type, offset, numElements, 0))
 2151 return;
 2152
 2153 clearIfComposited();
 2154
 2155 bool vertexAttrib0Simulated = false;
 2156 if (!isGLES2Compliant()) {
 2157 if (!numElements)
 2158 validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
 2159 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
 2160 }
 2161 if (!isGLES2NPOTStrict())
 2162 checkTextureCompleteness("drawElements", true);
 2163
 2164 m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
 2165
 2166 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 2167 restoreStatesAfterVertexAttrib0Simulation();
 2168 if (!isGLES2NPOTStrict())
 2169 checkTextureCompleteness("drawElements", false);
 2170 markContextChanged();
 2171}
 2172
 2173void WebGLRenderingContext::enable(GC3Denum cap)
 2174{
 2175 if (isContextLostOrPending() || !validateCapability("enable", cap))
 2176 return;
 2177 if (cap == GraphicsContext3D::STENCIL_TEST) {
 2178 m_stencilEnabled = true;
 2179 applyStencilTest();
 2180 return;
 2181 }
 2182 if (cap == GraphicsContext3D::SCISSOR_TEST) {
 2183 m_scissorEnabled = true;
 2184 if (m_drawingBuffer)
 2185 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
 2186 }
 2187 m_context->enable(cap);
 2188}
 2189
 2190void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
 2191{
 2192 UNUSED_PARAM(ec);
 2193 if (isContextLostOrPending())
 2194 return;
 2195 if (index >= m_maxVertexAttribs) {
 2196 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range");
 2197 return;
 2198 }
 2199
 2200 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
 2201 state.enabled = true;
 2202
 2203 m_context->enableVertexAttribArray(index);
 2204}
 2205
 2206void WebGLRenderingContext::finish()
 2207{
 2208 if (isContextLostOrPending())
 2209 return;
 2210 m_context->finish();
 2211}
 2212
 2213void WebGLRenderingContext::flush()
 2214{
 2215 if (isContextLostOrPending())
 2216 return;
 2217 m_context->flush();
 2218}
 2219
 2220void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
 2221{
 2222 UNUSED_PARAM(ec);
 2223 if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment))
 2224 return;
 2225 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
 2226 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target");
 2227 return;
 2228 }
 2229 if (buffer && !buffer->validate(contextGroup(), this)) {
 2230 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
 2231 return;
 2232 }
 2233 // Don't allow the default framebuffer to be mutated; all current
 2234 // implementations use an FBO internally in place of the default
 2235 // FBO.
 2236 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
 2237 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
 2238 return;
 2239 }
 2240 Platform3DObject bufferObject = objectOrZero(buffer);
 2241 switch (attachment) {
 2242 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
 2243 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
 2244 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
 2245 break;
 2246 default:
 2247 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
 2248 }
 2249 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
 2250 applyStencilTest();
 2251}
 2252
 2253void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
 2254{
 2255 UNUSED_PARAM(ec);
 2256 if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
 2257 return;
 2258 if (level) {
 2259 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
 2260 return;
 2261 }
 2262 if (texture && !texture->validate(contextGroup(), this)) {
 2263 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
 2264 return;
 2265 }
 2266 // Don't allow the default framebuffer to be mutated; all current
 2267 // implementations use an FBO internally in place of the default
 2268 // FBO.
 2269 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
 2270 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
 2271 return;
 2272 }
 2273 Platform3DObject textureObject = objectOrZero(texture);
 2274 switch (attachment) {
 2275 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
 2276 m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level);
 2277 m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level);
 2278 break;
 2279 case GraphicsContext3D::DEPTH_ATTACHMENT:
 2280 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
 2281 break;
 2282 case GraphicsContext3D::STENCIL_ATTACHMENT:
 2283 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
 2284 break;
 2285 default:
 2286 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
 2287 }
 2288 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
 2289 applyStencilTest();
 2290}
 2291
 2292void WebGLRenderingContext::frontFace(GC3Denum mode)
 2293{
 2294 if (isContextLostOrPending())
 2295 return;
 2296 m_context->frontFace(mode);
 2297}
 2298
 2299void WebGLRenderingContext::generateMipmap(GC3Denum target)
 2300{
 2301 if (isContextLostOrPending())
 2302 return;
 2303 WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
 2304 if (!tex)
 2305 return;
 2306 if (!tex->canGenerateMipmaps()) {
 2307 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size");
 2308 return;
 2309 }
 2310 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=123916. Compressed textures should be allowed in WebGL 2:
 2311 if (tex->isCompressed()) {
 2312 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture");
 2313 return;
 2314 }
 2315 if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
 2316 return;
 2317
 2318 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
 2319 // on Mac. Remove the hack once this driver bug is fixed.
 2320#if OS(DARWIN)
 2321 bool needToResetMinFilter = false;
 2322 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
 2323 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
 2324 needToResetMinFilter = true;
 2325 }
 2326#endif
 2327 m_context->generateMipmap(target);
 2328#if OS(DARWIN)
 2329 if (needToResetMinFilter)
 2330 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
 2331#endif
 2332 tex->generateMipmapLevelInfo();
 2333}
 2334
 2335PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
 2336{
 2337 UNUSED_PARAM(ec);
 2338 if (isContextLostOrPending() || !validateWebGLObject("getActiveAttrib", program))
 2339 return nullptr;
 2340 ActiveInfo info;
 2341 if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
 2342 return nullptr;
 2343
 2344 LOG(WebGL, "Returning active attribute %d: %s", index, info.name.utf8().data());
 2345
 2346 return WebGLActiveInfo::create(info.name, info.type, info.size);
 2347}
 2348
 2349PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
 2350{
 2351 UNUSED_PARAM(ec);
 2352 if (isContextLostOrPending() || !validateWebGLObject("getActiveUniform", program))
 2353 return 0;
 2354 ActiveInfo info;
 2355 if (!m_context->getActiveUniform(objectOrZero(program), index, info))
 2356 return nullptr;
 2357 if (!isGLES2Compliant())
 2358 if (info.size > 1 && !info.name.endsWith("[0]"))
 2359 info.name.append("[0]");
 2360
 2361 LOG(WebGL, "Returning active uniform %d: %s", index, info.name.utf8().data());
 2362
 2363 return WebGLActiveInfo::create(info.name, info.type, info.size);
 2364}
 2365
 2366bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader>>& shaderObjects, ExceptionCode& ec)
 2367{
 2368 UNUSED_PARAM(ec);
 2369 shaderObjects.clear();
 2370 if (isContextLostOrPending() || !validateWebGLObject("getAttachedShaders", program))
 2371 return false;
 2372
 2373 const GC3Denum shaderType[] = {
 2374 GraphicsContext3D::VERTEX_SHADER,
 2375 GraphicsContext3D::FRAGMENT_SHADER
 2376 };
 2377 for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
 2378 WebGLShader* shader = program->getAttachedShader(shaderType[i]);
 2379 if (shader)
 2380 shaderObjects.append(shader);
 2381 }
 2382 return true;
 2383}
 2384
 2385GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
 2386{
 2387 if (isContextLostOrPending() || !validateWebGLObject("getAttribLocation", program))
 2388 return -1;
 2389 if (!validateLocationLength("getAttribLocation", name))
 2390 return -1;
 2391 if (!validateString("getAttribLocation", name))
 2392 return -1;
 2393 if (isPrefixReserved(name))
 2394 return -1;
 2395 if (!program->getLinkStatus()) {
 2396 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked");
 2397 return -1;
 2398 }
 2399 return m_context->getAttribLocation(objectOrZero(program), name);
 2400}
 2401
 2402WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
 2403{
 2404 UNUSED_PARAM(ec);
 2405 if (isContextLostOrPending())
 2406 return WebGLGetInfo();
 2407 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
 2408 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
 2409 return WebGLGetInfo();
 2410 }
 2411
 2412 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
 2413 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
 2414 return WebGLGetInfo();
 2415 }
 2416
 2417 GC3Dint value = 0;
 2418 m_context->getBufferParameteriv(target, pname, &value);
 2419 if (pname == GraphicsContext3D::BUFFER_SIZE)
 2420 return WebGLGetInfo(value);
 2421 return WebGLGetInfo(static_cast<unsigned int>(value));
 2422}
 2423
 2424PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
 2425{
 2426 if (isContextLostOrPending())
 2427 return nullptr;
 2428 // We always need to return a new WebGLContextAttributes object to
 2429 // prevent the user from mutating any cached version.
 2430
 2431 // Also, we need to enforce requested values of "false" for depth
 2432 // and stencil, regardless of the properties of the underlying
 2433 // GraphicsContext3D or DrawingBuffer.
 2434 RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
 2435 if (!m_attributes.depth)
 2436 attributes->setDepth(false);
 2437 if (!m_attributes.stencil)
 2438 attributes->setStencil(false);
 2439 if (m_drawingBuffer) {
 2440 // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(),
 2441 // but it makes its own determination of whether multisampling is supported.
 2442 attributes->setAntialias(m_drawingBuffer->multisample());
 2443 }
 2444 return attributes.release();
 2445}
 2446
 2447GC3Denum WebGLRenderingContext::getError()
 2448{
 2449 if (m_isPendingPolicyResolution)
 2450 return GraphicsContext3D::NO_ERROR;
 2451 return m_context->getError();
 2452}
 2453
 2454WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
 2455{
 2456 if (isContextLostOrPending())
 2457 return nullptr;
 2458
 2459 if (equalIgnoringCase(name, "EXT_blend_minmax")
 2460 && m_context->getExtensions()->supports("GL_EXT_blend_minmax")) {
 2461 if (!m_extBlendMinMax) {
 2462 m_context->getExtensions()->ensureEnabled("GL_EXT_blend_minmax");
 2463 m_extBlendMinMax = std::make_unique<EXTBlendMinMax>(this);
 2464 }
 2465 return m_extBlendMinMax.get();
 2466 }
 2467 if (equalIgnoringCase(name, "EXT_sRGB")
 2468 && m_context->getExtensions()->supports("GL_EXT_sRGB")) {
 2469 if (!m_extsRGB) {
 2470 m_context->getExtensions()->ensureEnabled("GL_EXT_sRGB");
 2471 m_extsRGB = std::make_unique<EXTsRGB>(this);
 2472 }
 2473 return m_extsRGB.get();
 2474 }
 2475 if (equalIgnoringCase(name, "EXT_frag_depth")
 2476 && m_context->getExtensions()->supports("GL_EXT_frag_depth")) {
 2477 if (!m_extFragDepth) {
 2478 m_context->getExtensions()->ensureEnabled("GL_EXT_frag_depth");
 2479 m_extFragDepth = std::make_unique<EXTFragDepth>(this);
 2480 }
 2481 return m_extFragDepth.get();
 2482 }
 2483 if (equalIgnoringCase(name, "EXT_shader_texture_lod")
 2484 && (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))) {
 2485 if (!m_extShaderTextureLOD) {
 2486 m_context->getExtensions()->ensureEnabled("GL_EXT_shader_texture_lod");
 2487 m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(this);
 2488 }
 2489 return m_extShaderTextureLOD.get();
 2490 }
 2491 if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic")
 2492 && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
 2493 if (!m_extTextureFilterAnisotropic) {
 2494 m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
 2495 m_extTextureFilterAnisotropic = std::make_unique<EXTTextureFilterAnisotropic>(this);
 2496 }
 2497 return m_extTextureFilterAnisotropic.get();
 2498 }
 2499 if (equalIgnoringCase(name, "OES_standard_derivatives")
 2500 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
 2501 if (!m_oesStandardDerivatives) {
 2502 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
 2503 m_oesStandardDerivatives = std::make_unique<OESStandardDerivatives>(this);
 2504 }
 2505 return m_oesStandardDerivatives.get();
 2506 }
 2507 if (equalIgnoringCase(name, "OES_texture_float")
 2508 && m_context->getExtensions()->supports("GL_OES_texture_float")) {
 2509 if (!m_oesTextureFloat) {
 2510 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
 2511 m_oesTextureFloat = std::make_unique<OESTextureFloat>(this);
 2512 }
 2513 return m_oesTextureFloat.get();
 2514 }
 2515 if (equalIgnoringCase(name, "OES_texture_float_linear")
 2516 && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) {
 2517 if (!m_oesTextureFloatLinear) {
 2518 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear");
 2519 m_oesTextureFloatLinear = std::make_unique<OESTextureFloatLinear>(this);
 2520 }
 2521 return m_oesTextureFloatLinear.get();
 2522 }
 2523 if (equalIgnoringCase(name, "OES_texture_half_float")
 2524 && m_context->getExtensions()->supports("GL_OES_texture_half_float")) {
 2525 if (!m_oesTextureHalfFloat) {
 2526 m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float");
 2527 m_oesTextureHalfFloat = std::make_unique<OESTextureHalfFloat>(this);
 2528 }
 2529 return m_oesTextureHalfFloat.get();
 2530 }
 2531 if (equalIgnoringCase(name, "OES_texture_half_float_linear")
 2532 && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) {
 2533 if (!m_oesTextureHalfFloatLinear) {
 2534 m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear");
 2535 m_oesTextureHalfFloatLinear = std::make_unique<OESTextureHalfFloatLinear>(this);
 2536 }
 2537 return m_oesTextureHalfFloatLinear.get();
 2538 }
 2539 if (equalIgnoringCase(name, "OES_vertex_array_object")
 2540 && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
 2541 if (!m_oesVertexArrayObject) {
 2542 m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
 2543 m_oesVertexArrayObject = std::make_unique<OESVertexArrayObject>(this);
 2544 }
 2545 return m_oesVertexArrayObject.get();
 2546 }
 2547 if (equalIgnoringCase(name, "OES_element_index_uint")
 2548 && m_context->getExtensions()->supports("GL_OES_element_index_uint")) {
 2549 if (!m_oesElementIndexUint) {
 2550 m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint");
 2551 m_oesElementIndexUint = std::make_unique<OESElementIndexUint>(this);
 2552 }
 2553 return m_oesElementIndexUint.get();
 2554 }
 2555 if (equalIgnoringCase(name, "WEBGL_lose_context")) {
 2556 if (!m_webglLoseContext)
 2557 m_webglLoseContext = std::make_unique<WebGLLoseContext>(this);
 2558 return m_webglLoseContext.get();
 2559 }
 2560 if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_atc"))
 2561 && WebGLCompressedTextureATC::supported(this)) {
 2562 if (!m_webglCompressedTextureATC)
 2563 m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(this);
 2564 return m_webglCompressedTextureATC.get();
 2565 }
 2566 if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc"))
 2567 && WebGLCompressedTexturePVRTC::supported(this)) {
 2568 if (!m_webglCompressedTexturePVRTC)
 2569 m_webglCompressedTexturePVRTC = std::make_unique<WebGLCompressedTexturePVRTC>(this);
 2570 return m_webglCompressedTexturePVRTC.get();
 2571 }
 2572 if (equalIgnoringCase(name, "WEBGL_compressed_texture_s3tc")
 2573 && WebGLCompressedTextureS3TC::supported(this)) {
 2574 if (!m_webglCompressedTextureS3TC)
 2575 m_webglCompressedTextureS3TC = std::make_unique<WebGLCompressedTextureS3TC>(this);
 2576 return m_webglCompressedTextureS3TC.get();
 2577 }
 2578 if (equalIgnoringCase(name, "WEBGL_depth_texture")
 2579 && WebGLDepthTexture::supported(graphicsContext3D())) {
 2580 if (!m_webglDepthTexture) {
 2581 m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
 2582 m_webglDepthTexture = std::make_unique<WebGLDepthTexture>(this);
 2583 }
 2584 return m_webglDepthTexture.get();
 2585 }
 2586 if (equalIgnoringCase(name, "WEBGL_draw_buffers") && supportsDrawBuffers()) {
 2587 if (!m_webglDrawBuffers) {
 2588 m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
 2589 m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(this);
 2590 }
 2591 return m_webglDrawBuffers.get();
 2592 }
 2593 if (equalIgnoringCase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) {
 2594 if (!m_angleInstancedArrays) {
 2595 m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays");
 2596 m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(this);
 2597 }
 2598 return m_angleInstancedArrays.get();
 2599 }
 2600 if (allowPrivilegedExtensions()) {
 2601 if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) {
 2602 if (!m_webglDebugRendererInfo)
 2603 m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(this);
 2604 return m_webglDebugRendererInfo.get();
 2605 }
 2606 if (equalIgnoringCase(name, "WEBGL_debug_shaders")
 2607 && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
 2608 if (!m_webglDebugShaders)
 2609 m_webglDebugShaders = std::make_unique<WebGLDebugShaders>(this);
 2610 return m_webglDebugShaders.get();
 2611 }
 2612 }
 2613
 2614 return nullptr;
 2615}
 2616
 2617WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
 2618{
 2619 UNUSED_PARAM(ec);
 2620 if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
 2621 return WebGLGetInfo();
 2622
 2623 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
 2624 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
 2625 return WebGLGetInfo();
 2626 }
 2627
 2628 WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
 2629 if (!object) {
 2630 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
 2631 return WebGLGetInfo(GraphicsContext3D::NONE);
 2632 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
 2633 // specifies INVALID_OPERATION.
 2634 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
 2635 return WebGLGetInfo();
 2636 }
 2637
 2638 ASSERT(object->isTexture() || object->isRenderbuffer());
 2639 if (object->isTexture()) {
 2640 switch (pname) {
 2641 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
 2642 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
 2643 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
 2644 return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
 2645 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
 2646 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
 2647 case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
 2648 GC3Dint value = 0;
 2649 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
 2650 return WebGLGetInfo(value);
 2651 }
 2652 default:
 2653 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
 2654 return WebGLGetInfo();
 2655 }
 2656 } else {
 2657 switch (pname) {
 2658 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
 2659 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
 2660 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
 2661 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
 2662 case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
 2663 WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
 2664 GC3Denum renderBufferFormat = renderBuffer->getInternalFormat();
 2665 ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT);
 2666 if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT)
 2667 return WebGLGetInfo(Extensions3D::SRGB_EXT);
 2668 return WebGLGetInfo(GraphicsContext3D::LINEAR);
 2669 }
 2670 default:
 2671 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
 2672 return WebGLGetInfo();
 2673 }
 2674 }
 2675}
 2676
 2677WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
 2678{
 2679 UNUSED_PARAM(ec);
 2680 if (isContextLostOrPending())
 2681 return WebGLGetInfo();
 2682 const int intZero = 0;
 2683 switch (pname) {
 2684 case GraphicsContext3D::ACTIVE_TEXTURE:
 2685 return getUnsignedIntParameter(pname);
 2686 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
 2687 return getWebGLFloatArrayParameter(pname);
 2688 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
 2689 return getWebGLFloatArrayParameter(pname);
 2690 case GraphicsContext3D::ALPHA_BITS:
 2691 return getIntParameter(pname);
 2692 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
 2693 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
 2694 case GraphicsContext3D::BLEND:
 2695 return getBooleanParameter(pname);
 2696 case GraphicsContext3D::BLEND_COLOR:
 2697 return getWebGLFloatArrayParameter(pname);
 2698 case GraphicsContext3D::BLEND_DST_ALPHA:
 2699 return getUnsignedIntParameter(pname);
 2700 case GraphicsContext3D::BLEND_DST_RGB:
 2701 return getUnsignedIntParameter(pname);
 2702 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
 2703 return getUnsignedIntParameter(pname);
 2704 case GraphicsContext3D::BLEND_EQUATION_RGB:
 2705 return getUnsignedIntParameter(pname);
 2706 case GraphicsContext3D::BLEND_SRC_ALPHA:
 2707 return getUnsignedIntParameter(pname);
 2708 case GraphicsContext3D::BLEND_SRC_RGB:
 2709 return getUnsignedIntParameter(pname);
 2710 case GraphicsContext3D::BLUE_BITS:
 2711 return getIntParameter(pname);
 2712 case GraphicsContext3D::COLOR_CLEAR_VALUE:
 2713 return getWebGLFloatArrayParameter(pname);
 2714 case GraphicsContext3D::COLOR_WRITEMASK:
 2715 return getBooleanArrayParameter(pname);
 2716 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
 2717 return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()));
 2718 case GraphicsContext3D::CULL_FACE:
 2719 return getBooleanParameter(pname);
 2720 case GraphicsContext3D::CULL_FACE_MODE:
 2721 return getUnsignedIntParameter(pname);
 2722 case GraphicsContext3D::CURRENT_PROGRAM:
 2723 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
 2724 case GraphicsContext3D::DEPTH_BITS:
 2725 if (!m_framebufferBinding && !m_attributes.depth)
 2726 return WebGLGetInfo(intZero);
 2727 return getIntParameter(pname);
 2728 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
 2729 return getFloatParameter(pname);
 2730 case GraphicsContext3D::DEPTH_FUNC:
 2731 return getUnsignedIntParameter(pname);
 2732 case GraphicsContext3D::DEPTH_RANGE:
 2733 return getWebGLFloatArrayParameter(pname);
 2734 case GraphicsContext3D::DEPTH_TEST:
 2735 return getBooleanParameter(pname);
 2736 case GraphicsContext3D::DEPTH_WRITEMASK:
 2737 return getBooleanParameter(pname);
 2738 case GraphicsContext3D::DITHER:
 2739 return getBooleanParameter(pname);
 2740 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
 2741 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
 2742 case GraphicsContext3D::FRAMEBUFFER_BINDING:
 2743 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
 2744 case GraphicsContext3D::FRONT_FACE:
 2745 return getUnsignedIntParameter(pname);
 2746 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
 2747 return getUnsignedIntParameter(pname);
 2748 case GraphicsContext3D::GREEN_BITS:
 2749 return getIntParameter(pname);
 2750 case GraphicsContext3D::LINE_WIDTH:
 2751 return getFloatParameter(pname);
 2752 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
 2753 return getIntParameter(pname);
 2754 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
 2755 return getIntParameter(pname);
 2756 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
 2757 return getIntParameter(pname);
 2758 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
 2759 return getIntParameter(pname);
 2760 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
 2761 return getIntParameter(pname);
 2762 case GraphicsContext3D::MAX_TEXTURE_SIZE:
 2763 return getIntParameter(pname);
 2764 case GraphicsContext3D::MAX_VARYING_VECTORS:
 2765 return getIntParameter(pname);
 2766 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
 2767 return getIntParameter(pname);
 2768 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
 2769 return getIntParameter(pname);
 2770 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
 2771 return getIntParameter(pname);
 2772 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
 2773 return getWebGLIntArrayParameter(pname);
 2774 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
 2775 // FIXME: should we always return 0 for this?
 2776 return getIntParameter(pname);
 2777 case GraphicsContext3D::PACK_ALIGNMENT:
 2778 return getIntParameter(pname);
 2779 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
 2780 return getFloatParameter(pname);
 2781 case GraphicsContext3D::POLYGON_OFFSET_FILL:
 2782 return getBooleanParameter(pname);
 2783 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
 2784 return getFloatParameter(pname);
 2785 case GraphicsContext3D::RED_BITS:
 2786 return getIntParameter(pname);
 2787 case GraphicsContext3D::RENDERBUFFER_BINDING:
 2788 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
 2789 case GraphicsContext3D::RENDERER:
 2790 return WebGLGetInfo(String("WebKit WebGL"));
 2791 case GraphicsContext3D::SAMPLE_BUFFERS:
 2792 return getIntParameter(pname);
 2793 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
 2794 return getBooleanParameter(pname);
 2795 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
 2796 return getFloatParameter(pname);
 2797 case GraphicsContext3D::SAMPLES:
 2798 return getIntParameter(pname);
 2799 case GraphicsContext3D::SCISSOR_BOX:
 2800 return getWebGLIntArrayParameter(pname);
 2801 case GraphicsContext3D::SCISSOR_TEST:
 2802 return getBooleanParameter(pname);
 2803 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
 2804 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
 2805 case GraphicsContext3D::STENCIL_BACK_FAIL:
 2806 return getUnsignedIntParameter(pname);
 2807 case GraphicsContext3D::STENCIL_BACK_FUNC:
 2808 return getUnsignedIntParameter(pname);
 2809 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
 2810 return getUnsignedIntParameter(pname);
 2811 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
 2812 return getUnsignedIntParameter(pname);
 2813 case GraphicsContext3D::STENCIL_BACK_REF:
 2814 return getIntParameter(pname);
 2815 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
 2816 return getUnsignedIntParameter(pname);
 2817 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
 2818 return getUnsignedIntParameter(pname);
 2819 case GraphicsContext3D::STENCIL_BITS:
 2820 if (!m_framebufferBinding && !m_attributes.stencil)
 2821 return WebGLGetInfo(intZero);
 2822 return getIntParameter(pname);
 2823 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
 2824 return getIntParameter(pname);
 2825 case GraphicsContext3D::STENCIL_FAIL:
 2826 return getUnsignedIntParameter(pname);
 2827 case GraphicsContext3D::STENCIL_FUNC:
 2828 return getUnsignedIntParameter(pname);
 2829 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
 2830 return getUnsignedIntParameter(pname);
 2831 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
 2832 return getUnsignedIntParameter(pname);
 2833 case GraphicsContext3D::STENCIL_REF:
 2834 return getIntParameter(pname);
 2835 case GraphicsContext3D::STENCIL_TEST:
 2836 return getBooleanParameter(pname);
 2837 case GraphicsContext3D::STENCIL_VALUE_MASK:
 2838 return getUnsignedIntParameter(pname);
 2839 case GraphicsContext3D::STENCIL_WRITEMASK:
 2840 return getUnsignedIntParameter(pname);
 2841 case GraphicsContext3D::SUBPIXEL_BITS:
 2842 return getIntParameter(pname);
 2843 case GraphicsContext3D::TEXTURE_BINDING_2D:
 2844 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding));
 2845 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
 2846 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding));
 2847 case GraphicsContext3D::UNPACK_ALIGNMENT:
 2848 return getIntParameter(pname);
 2849 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
 2850 return WebGLGetInfo(m_unpackFlipY);
 2851 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
 2852 return WebGLGetInfo(m_unpackPremultiplyAlpha);
 2853 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
 2854 return WebGLGetInfo(m_unpackColorspaceConversion);
 2855 case GraphicsContext3D::VENDOR:
 2856 return WebGLGetInfo(String("WebKit"));
 2857 case GraphicsContext3D::VERSION:
 2858 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
 2859 case GraphicsContext3D::VIEWPORT:
 2860 return getWebGLIntArrayParameter(pname);
 2861 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
 2862 if (m_oesStandardDerivatives)
 2863 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
 2864 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
 2865 return WebGLGetInfo();
 2866 case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
 2867 if (m_webglDebugRendererInfo)
 2868 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
 2869 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
 2870 return WebGLGetInfo();
 2871 case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
 2872 if (m_webglDebugRendererInfo)
 2873 return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
 2874 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
 2875 return WebGLGetInfo();
 2876 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
 2877 if (m_oesVertexArrayObject) {
 2878 if (!m_boundVertexArrayObject->isDefaultObject())
 2879 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
 2880 return WebGLGetInfo();
 2881 }
 2882 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
 2883 return WebGLGetInfo();
 2884 case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
 2885 if (m_extTextureFilterAnisotropic)
 2886 return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
 2887 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
 2888 return WebGLGetInfo();
 2889 case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
 2890 if (m_webglDrawBuffers)
 2891 return WebGLGetInfo(getMaxColorAttachments());
 2892 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
 2893 return WebGLGetInfo();
 2894 case Extensions3D::MAX_DRAW_BUFFERS_EXT:
 2895 if (m_webglDrawBuffers)
 2896 return WebGLGetInfo(getMaxDrawBuffers());
 2897 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
 2898 return WebGLGetInfo();
 2899 default:
 2900 if (m_webglDrawBuffers
 2901 && pname >= Extensions3D::DRAW_BUFFER0_EXT
 2902 && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
 2903 GC3Dint value = GraphicsContext3D::NONE;
 2904 if (m_framebufferBinding)
 2905 value = m_framebufferBinding->getDrawBuffer(pname);
 2906 else // emulated backbuffer
 2907 value = m_backDrawBuffer;
 2908 return WebGLGetInfo(value);
 2909 }
 2910 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
 2911 return WebGLGetInfo();
 2912 }
 2913}
 2914
 2915WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
 2916{
 2917 UNUSED_PARAM(ec);
 2918 if (isContextLostOrPending() || !validateWebGLObject("getProgramParameter", program))
 2919 return WebGLGetInfo();
 2920
 2921 GC3Dint value = 0;
 2922 switch (pname) {
 2923 case GraphicsContext3D::DELETE_STATUS:
 2924 return WebGLGetInfo(program->isDeleted());
 2925 case GraphicsContext3D::VALIDATE_STATUS:
 2926 m_context->getProgramiv(objectOrZero(program), pname, &value);
 2927 return WebGLGetInfo(static_cast<bool>(value));
 2928 case GraphicsContext3D::LINK_STATUS:
 2929 return WebGLGetInfo(program->getLinkStatus());
 2930 case GraphicsContext3D::ATTACHED_SHADERS:
 2931 m_context->getProgramiv(objectOrZero(program), pname, &value);
 2932 return WebGLGetInfo(value);
 2933 case GraphicsContext3D::ACTIVE_ATTRIBUTES:
 2934 case GraphicsContext3D::ACTIVE_UNIFORMS:
 2935 m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), pname, &value);
 2936 return WebGLGetInfo(value);
 2937 default:
 2938 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name");
 2939 return WebGLGetInfo();
 2940 }
 2941}
 2942
 2943String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
 2944{
 2945 UNUSED_PARAM(ec);
 2946 if (isContextLostOrPending())
 2947 return String();
 2948 if (!validateWebGLObject("getProgramInfoLog", program))
 2949 return "";
 2950 return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
 2951}
 2952
 2953WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
 2954{
 2955 UNUSED_PARAM(ec);
 2956 if (isContextLostOrPending())
 2957 return WebGLGetInfo();
 2958 if (target != GraphicsContext3D::RENDERBUFFER) {
 2959 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target");
 2960 return WebGLGetInfo();
 2961 }
 2962 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
 2963 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound");
 2964 return WebGLGetInfo();
 2965 }
 2966
 2967 if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
 2968 && !m_renderbufferBinding->isValid()) {
 2969 ASSERT(!isDepthStencilSupported());
 2970 int value = 0;
 2971 switch (pname) {
 2972 case GraphicsContext3D::RENDERBUFFER_WIDTH:
 2973 value = m_renderbufferBinding->getWidth();
 2974 break;
 2975 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
 2976 value = m_renderbufferBinding->getHeight();
 2977 break;
 2978 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
 2979 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
 2980 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
 2981 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
 2982 value = 0;
 2983 break;
 2984 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
 2985 value = 24;
 2986 break;
 2987 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
 2988 value = 8;
 2989 break;
 2990 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
 2991 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
 2992 default:
 2993 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
 2994 return WebGLGetInfo();
 2995 }
 2996 return WebGLGetInfo(value);
 2997 }
 2998
 2999 GC3Dint value = 0;
 3000 switch (pname) {
 3001 case GraphicsContext3D::RENDERBUFFER_WIDTH:
 3002 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
 3003 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
 3004 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
 3005 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
 3006 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
 3007 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
 3008 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
 3009 m_context->getRenderbufferParameteriv(target, pname, &value);
 3010 return WebGLGetInfo(value);
 3011 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
 3012 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
 3013 default:
 3014 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
 3015 return WebGLGetInfo();
 3016 }
 3017}
 3018
 3019WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
 3020{
 3021 UNUSED_PARAM(ec);
 3022 if (isContextLostOrPending() || !validateWebGLObject("getShaderParameter", shader))
 3023 return WebGLGetInfo();
 3024 GC3Dint value = 0;
 3025 switch (pname) {
 3026 case GraphicsContext3D::DELETE_STATUS:
 3027 return WebGLGetInfo(shader->isDeleted());
 3028 case GraphicsContext3D::COMPILE_STATUS:
 3029 m_context->getShaderiv(objectOrZero(shader), pname, &value);
 3030 return WebGLGetInfo(static_cast<bool>(value));
 3031 case GraphicsContext3D::SHADER_TYPE:
 3032 m_context->getShaderiv(objectOrZero(shader), pname, &value);
 3033 return WebGLGetInfo(static_cast<unsigned int>(value));
 3034 default:
 3035 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
 3036 return WebGLGetInfo();
 3037 }
 3038}
 3039
 3040String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
 3041{
 3042 UNUSED_PARAM(ec);
 3043 if (isContextLostOrPending())
 3044 return String();
 3045 if (!validateWebGLObject("getShaderInfoLog", shader))
 3046 return "";
 3047 return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
 3048}
 3049
 3050PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec)
 3051{
 3052 UNUSED_PARAM(ec);
 3053 if (isContextLostOrPending())
 3054 return nullptr;
 3055 switch (shaderType) {
 3056 case GraphicsContext3D::VERTEX_SHADER:
 3057 case GraphicsContext3D::FRAGMENT_SHADER:
 3058 break;
 3059 default:
 3060 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type");
 3061 return nullptr;
 3062 }
 3063 switch (precisionType) {
 3064 case GraphicsContext3D::LOW_FLOAT:
 3065 case GraphicsContext3D::MEDIUM_FLOAT:
 3066 case GraphicsContext3D::HIGH_FLOAT:
 3067 case GraphicsContext3D::LOW_INT:
 3068 case GraphicsContext3D::MEDIUM_INT:
 3069 case GraphicsContext3D::HIGH_INT:
 3070 break;
 3071 default:
 3072 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type");
 3073 return nullptr;
 3074 }
 3075
 3076 GC3Dint range[2] = {0, 0};
 3077 GC3Dint precision = 0;
 3078 m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision);
 3079 return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
 3080}
 3081
 3082String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
 3083{
 3084 UNUSED_PARAM(ec);
 3085 if (isContextLostOrPending())
 3086 return String();
 3087 if (!validateWebGLObject("getShaderSource", shader))
 3088 return "";
 3089 return ensureNotNull(shader->getSource());
 3090}
 3091
 3092Vector<String> WebGLRenderingContext::getSupportedExtensions()
 3093{
 3094 Vector<String> result;
 3095
 3096 if (m_isPendingPolicyResolution)
 3097 return result;
 3098
 3099 if (m_context->getExtensions()->supports("GL_EXT_blend_minmax"))
 3100 result.append("EXT_blend_minmax");
 3101 if (m_context->getExtensions()->supports("GL_EXT_sRGB"))
 3102 result.append("EXT_sRGB");
 3103 if (m_context->getExtensions()->supports("GL_EXT_frag_depth"))
 3104 result.append("EXT_frag_depth");
 3105 if (m_context->getExtensions()->supports("GL_OES_texture_float"))
 3106 result.append("OES_texture_float");
 3107 if (m_context->getExtensions()->supports("GL_OES_texture_float_linear"))
 3108 result.append("OES_texture_float_linear");
 3109 if (m_context->getExtensions()->supports("GL_OES_texture_half_float"))
 3110 result.append("OES_texture_half_float");
 3111 if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear"))
 3112 result.append("OES_texture_half_float_linear");
 3113 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
 3114 result.append("OES_standard_derivatives");
 3115 if (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))
 3116 result.append("EXT_shader_texture_lod");
 3117 if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
 3118 result.append("WEBKIT_EXT_texture_filter_anisotropic");
 3119 if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
 3120 result.append("OES_vertex_array_object");
 3121 if (m_context->getExtensions()->supports("GL_OES_element_index_uint"))
 3122 result.append("OES_element_index_uint");
 3123 result.append("WEBGL_lose_context");
 3124 if (WebGLCompressedTextureATC::supported(this))
 3125 result.append("WEBKIT_WEBGL_compressed_texture_atc");
 3126 if (WebGLCompressedTexturePVRTC::supported(this))
 3127 result.append("WEBKIT_WEBGL_compressed_texture_pvrtc");
 3128 if (WebGLCompressedTextureS3TC::supported(this))
 3129 result.append("WEBGL_compressed_texture_s3tc");
 3130 if (WebGLDepthTexture::supported(graphicsContext3D()))
 3131 result.append("WEBGL_depth_texture");
 3132 if (supportsDrawBuffers())
 3133 result.append("WEBGL_draw_buffers");
 3134 if (ANGLEInstancedArrays::supported(this))
 3135 result.append("ANGLE_instanced_arrays");
 3136
 3137 if (allowPrivilegedExtensions()) {
 3138 if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
 3139 result.append("WEBGL_debug_shaders");
 3140 result.append("WEBGL_debug_renderer_info");
 3141 }
 3142
 3143 return result;
 3144}
 3145
 3146WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
 3147{
 3148 UNUSED_PARAM(ec);
 3149 if (isContextLostOrPending())
 3150 return WebGLGetInfo();
 3151 WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false);
 3152 if (!tex)
 3153 return WebGLGetInfo();
 3154 GC3Dint value = 0;
 3155 switch (pname) {
 3156 case GraphicsContext3D::TEXTURE_MAG_FILTER:
 3157 case GraphicsContext3D::TEXTURE_MIN_FILTER:
 3158 case GraphicsContext3D::TEXTURE_WRAP_S:
 3159 case GraphicsContext3D::TEXTURE_WRAP_T:
 3160 m_context->getTexParameteriv(target, pname, &value);
 3161 return WebGLGetInfo(static_cast<unsigned int>(value));
 3162 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
 3163 if (m_extTextureFilterAnisotropic) {
 3164 m_context->getTexParameteriv(target, pname, &value);
 3165 return WebGLGetInfo(static_cast<unsigned int>(value));
 3166 }
 3167 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
 3168 return WebGLGetInfo();
 3169 default:
 3170 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name");
 3171 return WebGLGetInfo();
 3172 }
 3173}
 3174
 3175WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
 3176{
 3177 UNUSED_PARAM(ec);
 3178 if (isContextLostOrPending() || !validateWebGLObject("getUniform", program))
 3179 return WebGLGetInfo();
 3180 if (!uniformLocation || uniformLocation->program() != program) {
 3181 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program");
 3182 return WebGLGetInfo();
 3183 }
 3184 GC3Dint location = uniformLocation->location();
 3185
 3186 GC3Denum baseType;
 3187 unsigned length;
 3188 switch (uniformLocation->type()) {
 3189 case GraphicsContext3D::BOOL:
 3190 baseType = GraphicsContext3D::BOOL;
 3191 length = 1;
 3192 break;
 3193 case GraphicsContext3D::BOOL_VEC2:
 3194 baseType = GraphicsContext3D::BOOL;
 3195 length = 2;
 3196 break;
 3197 case GraphicsContext3D::BOOL_VEC3:
 3198 baseType = GraphicsContext3D::BOOL;
 3199 length = 3;
 3200 break;
 3201 case GraphicsContext3D::BOOL_VEC4:
 3202 baseType = GraphicsContext3D::BOOL;
 3203 length = 4;
 3204 break;
 3205 case GraphicsContext3D::INT:
 3206 baseType = GraphicsContext3D::INT;
 3207 length = 1;
 3208 break;
 3209 case GraphicsContext3D::INT_VEC2:
 3210 baseType = GraphicsContext3D::INT;
 3211 length = 2;
 3212 break;
 3213 case GraphicsContext3D::INT_VEC3:
 3214 baseType = GraphicsContext3D::INT;
 3215 length = 3;
 3216 break;
 3217 case GraphicsContext3D::INT_VEC4:
 3218 baseType = GraphicsContext3D::INT;
 3219 length = 4;
 3220 break;
 3221 case GraphicsContext3D::FLOAT:
 3222 baseType = GraphicsContext3D::FLOAT;
 3223 length = 1;
 3224 break;
 3225 case GraphicsContext3D::FLOAT_VEC2:
 3226 baseType = GraphicsContext3D::FLOAT;
 3227 length = 2;
 3228 break;
 3229 case GraphicsContext3D::FLOAT_VEC3:
 3230 baseType = GraphicsContext3D::FLOAT;
 3231 length = 3;
 3232 break;
 3233 case GraphicsContext3D::FLOAT_VEC4:
 3234 baseType = GraphicsContext3D::FLOAT;
 3235 length = 4;
 3236 break;
 3237 case GraphicsContext3D::FLOAT_MAT2:
 3238 baseType = GraphicsContext3D::FLOAT;
 3239 length = 4;
 3240 break;
 3241 case GraphicsContext3D::FLOAT_MAT3:
 3242 baseType = GraphicsContext3D::FLOAT;
 3243 length = 9;
 3244 break;
 3245 case GraphicsContext3D::FLOAT_MAT4:
 3246 baseType = GraphicsContext3D::FLOAT;
 3247 length = 16;
 3248 break;
 3249 case GraphicsContext3D::SAMPLER_2D:
 3250 case GraphicsContext3D::SAMPLER_CUBE:
 3251 baseType = GraphicsContext3D::INT;
 3252 length = 1;
 3253 break;
 3254 default:
 3255 // Can't handle this type
 3256 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type");
 3257 return WebGLGetInfo();
 3258 }
 3259 switch (baseType) {
 3260 case GraphicsContext3D::FLOAT: {
 3261 GC3Dfloat value[16] = {0};
 3262 if (m_isRobustnessEXTSupported)
 3263 m_context->getExtensions()->getnUniformfvEXT(objectOrZero(program), location, 16 * sizeof(GC3Dfloat), value);
 3264 else
 3265 m_context->getUniformfv(objectOrZero(program), location, value);
 3266 if (length == 1)
 3267 return WebGLGetInfo(value[0]);
 3268 return WebGLGetInfo(Float32Array::create(value, length));
 3269 }
 3270 case GraphicsContext3D::INT: {
 3271 GC3Dint value[4] = {0};
 3272 if (m_isRobustnessEXTSupported)
 3273 m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
 3274 else
 3275 m_context->getUniformiv(objectOrZero(program), location, value);
 3276 if (length == 1)
 3277 return WebGLGetInfo(value[0]);
 3278 return WebGLGetInfo(Int32Array::create(value, length));
 3279 }
 3280 case GraphicsContext3D::BOOL: {
 3281 GC3Dint value[4] = {0};
 3282 if (m_isRobustnessEXTSupported)
 3283 m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
 3284 else
 3285 m_context->getUniformiv(objectOrZero(program), location, value);
 3286 if (length > 1) {
 3287 bool boolValue[16] = {0};
 3288 for (unsigned j = 0; j < length; j++)
 3289 boolValue[j] = static_cast<bool>(value[j]);
 3290 return WebGLGetInfo(boolValue, length);
 3291 }
 3292 return WebGLGetInfo(static_cast<bool>(value[0]));
 3293 }
 3294 default:
 3295 notImplemented();
 3296 }
 3297
 3298 // If we get here, something went wrong in our unfortunately complex logic above
 3299 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error");
 3300 return WebGLGetInfo();
 3301}
 3302
 3303PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
 3304{
 3305 UNUSED_PARAM(ec);
 3306 if (isContextLostOrPending() || !validateWebGLObject("getUniformLocation", program))
 3307 return nullptr;
 3308 if (!validateLocationLength("getUniformLocation", name))
 3309 return nullptr;
 3310 if (!validateString("getUniformLocation", name))
 3311 return nullptr;
 3312 if (isPrefixReserved(name))
 3313 return nullptr;
 3314 if (!program->getLinkStatus()) {
 3315 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked");
 3316 return nullptr;
 3317 }
 3318 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
 3319 if (uniformLocation == -1)
 3320 return nullptr;
 3321
 3322 GC3Dint activeUniforms = 0;
 3323 m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
 3324 for (GC3Dint i = 0; i < activeUniforms; i++) {
 3325 ActiveInfo info;
 3326 if (!m_context->getActiveUniform(objectOrZero(program), i, info))
 3327 return nullptr;
 3328 // Strip "[0]" from the name if it's an array.
 3329 if (info.name.endsWith("[0]"))
 3330 info.name = info.name.left(info.name.length() - 3);
 3331 // If it's an array, we need to iterate through each element, appending "[index]" to the name.
 3332 for (GC3Dint index = 0; index < info.size; ++index) {
 3333 String uniformName = info.name + "[" + String::number(index) + "]";
 3334
 3335 if (name == uniformName || name == info.name)
 3336 return WebGLUniformLocation::create(program, uniformLocation, info.type);
 3337 }
 3338 }
 3339 return nullptr;
 3340}
 3341
 3342WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
 3343{
 3344 UNUSED_PARAM(ec);
 3345
 3346 if (isContextLostOrPending())
 3347 return WebGLGetInfo();
 3348
 3349 if (index >= m_maxVertexAttribs) {
 3350 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range");
 3351 return WebGLGetInfo();
 3352 }
 3353
 3354 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
 3355
 3356 if (m_angleInstancedArrays && pname == GraphicsContext3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE)
 3357 return WebGLGetInfo(state.divisor);
 3358
 3359 switch (pname) {
 3360 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
 3361 if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
 3362 || !state.bufferBinding
 3363 || !state.bufferBinding->object())
 3364 return WebGLGetInfo();
 3365 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
 3366 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
 3367 return WebGLGetInfo(state.enabled);
 3368 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
 3369 return WebGLGetInfo(state.normalized);
 3370 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
 3371 return WebGLGetInfo(state.size);
 3372 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
 3373 return WebGLGetInfo(state.originalStride);
 3374 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
 3375 return WebGLGetInfo(state.type);
 3376 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
 3377 return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
 3378 default:
 3379 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name");
 3380 return WebGLGetInfo();
 3381 }
 3382}
 3383
 3384long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
 3385{
 3386 if (isContextLostOrPending())
 3387 return 0;
 3388 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
 3389 return static_cast<long long>(result);
 3390}
 3391
 3392void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
 3393{
 3394 if (isContextLostOrPending())
 3395 return;
 3396 bool isValid = false;
 3397 switch (target) {
 3398 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
 3399 isValid = true;
 3400 break;
 3401 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
 3402 if (m_oesStandardDerivatives)
 3403 isValid = true;
 3404 break;
 3405 }
 3406 if (!isValid) {
 3407 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
 3408 return;
 3409 }
 3410 m_context->hint(target, mode);
 3411}
 3412
 3413GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
 3414{
 3415 if (!buffer || isContextLostOrPending())
 3416 return 0;
 3417
 3418 if (!buffer->hasEverBeenBound())
 3419 return 0;
 3420
 3421 return m_context->isBuffer(buffer->object());
 3422}
 3423
 3424bool WebGLRenderingContext::isContextLost() const
 3425{
 3426 return m_contextLost;
 3427}
 3428
 3429bool WebGLRenderingContext::isContextLostOrPending()
 3430{
 3431 if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) {
 3432 LOG(WebGL, "Context is being used. Attempt to resolve the policy.");
 3433 Document& document = canvas()->document().topDocument();
 3434 Page* page = document.page();
 3435 if (page && !document.url().isLocalFile())
 3436 page->mainFrame().loader().client().resolveWebGLPolicyForURL(document.url());
 3437 // FIXME: We don't currently do anything with the result from resolution. A more
 3438 // complete implementation might try to construct a real context, etc and proceed
 3439 // with normal operation.
 3440 // https://bugs.webkit.org/show_bug.cgi?id=129122
 3441 m_hasRequestedPolicyResolution = true;
 3442 }
 3443
 3444 return m_contextLost || m_isPendingPolicyResolution;
 3445}
 3446
 3447GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
 3448{
 3449 if (isContextLostOrPending() || !validateCapability("isEnabled", cap))
 3450 return 0;
 3451 if (cap == GraphicsContext3D::STENCIL_TEST)
 3452 return m_stencilEnabled;
 3453 return m_context->isEnabled(cap);
 3454}
 3455
 3456GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
 3457{
 3458 if (!framebuffer || isContextLostOrPending())
 3459 return 0;
 3460
 3461 if (!framebuffer->hasEverBeenBound())
 3462 return 0;
 3463
 3464 return m_context->isFramebuffer(framebuffer->object());
 3465}
 3466
 3467GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
 3468{
 3469 if (!program || isContextLostOrPending())
 3470 return 0;
 3471
 3472 return m_context->isProgram(program->object());
 3473}
 3474
 3475GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
 3476{
 3477 if (!renderbuffer || isContextLostOrPending())
 3478 return 0;
 3479
 3480 if (!renderbuffer->hasEverBeenBound())
 3481 return 0;
 3482
 3483 return m_context->isRenderbuffer(renderbuffer->object());
 3484}
 3485
 3486GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
 3487{
 3488 if (!shader || isContextLostOrPending())
 3489 return 0;
 3490
 3491 return m_context->isShader(shader->object());
 3492}
 3493
 3494GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
 3495{
 3496 if (!texture || isContextLostOrPending())
 3497 return 0;
 3498
 3499 if (!texture->hasEverBeenBound())
 3500 return 0;
 3501
 3502 return m_context->isTexture(texture->object());
 3503}
 3504
 3505void WebGLRenderingContext::lineWidth(GC3Dfloat width)
 3506{
 3507 if (isContextLostOrPending())
 3508 return;
 3509 m_context->lineWidth(width);
 3510}
 3511
 3512void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
 3513{
 3514 UNUSED_PARAM(ec);
 3515 if (isContextLostOrPending() || !validateWebGLObject("linkProgram", program))
 3516 return;
 3517 if (!isGLES2Compliant()) {
 3518 WebGLShader* vertexShader = program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER);
 3519 WebGLShader* fragmentShader = program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER);
 3520 if (!vertexShader || !vertexShader->isValid() || !fragmentShader || !fragmentShader->isValid() || !m_context->precisionsMatch(objectOrZero(vertexShader), objectOrZero(fragmentShader)) || !m_context->checkVaryingsPacking(objectOrZero(vertexShader), objectOrZero(fragmentShader))) {
 3521 program->setLinkStatus(false);
 3522 return;
 3523 }
 3524 }
 3525
 3526 m_context->linkProgram(objectOrZero(program));
 3527 program->increaseLinkCount();
 3528}
 3529
 3530void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
 3531{
 3532 if (isContextLostOrPending())
 3533 return;
 3534 switch (pname) {
 3535 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
 3536 m_unpackFlipY = param;
 3537 break;
 3538 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
 3539 m_unpackPremultiplyAlpha = param;
 3540 break;
 3541 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
 3542 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
 3543 m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
 3544 else {
 3545 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
 3546 return;
 3547 }
 3548 break;
 3549 case GraphicsContext3D::PACK_ALIGNMENT:
 3550 case GraphicsContext3D::UNPACK_ALIGNMENT:
 3551 if (param == 1 || param == 2 || param == 4 || param == 8) {
 3552 if (pname == GraphicsContext3D::PACK_ALIGNMENT)
 3553 m_packAlignment = param;
 3554 else // GraphicsContext3D::UNPACK_ALIGNMENT:
 3555 m_unpackAlignment = param;
 3556 m_context->pixelStorei(pname, param);
 3557 } else {
 3558 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment");
 3559 return;
 3560 }
 3561 break;
 3562 default:
 3563 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name");
 3564 return;
 3565 }
 3566}
 3567
 3568void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
 3569{
 3570 if (isContextLostOrPending())
 3571 return;
 3572 m_context->polygonOffset(factor, units);
 3573}
 3574
 3575void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
 3576{
 3577 if (isContextLostOrPending())
 3578 return;
 3579 // Due to WebGL's same-origin restrictions, it is not possible to
 3580 // taint the origin using the WebGL API.
 3581 ASSERT(canvas()->originClean());
 3582 // Validate input parameters.
 3583 if (!pixels) {
 3584 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView");
 3585 return;
 3586 }
 3587 switch (format) {
 3588 case GraphicsContext3D::ALPHA:
 3589 case GraphicsContext3D::RGB:
 3590 case GraphicsContext3D::RGBA:
 3591 break;
 3592 default:
 3593 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
 3594 return;
 3595 }
 3596 switch (type) {
 3597 case GraphicsContext3D::UNSIGNED_BYTE:
 3598 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
 3599 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
 3600 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
 3601 break;
 3602 default:
 3603 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
 3604 return;
 3605 }
 3606 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
 3607 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
 3608 return;
 3609 }
 3610 // Validate array type against pixel type.
 3611 if (pixels->getType() != JSC::TypeUint8) {
 3612 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
 3613 return;
 3614 }
 3615 const char* reason = "framebuffer incomplete";
 3616 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 3617 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
 3618 return;
 3619 }
 3620 // Calculate array size, taking into consideration of PACK_ALIGNMENT.
 3621 unsigned int totalBytesRequired = 0;
 3622 unsigned int padding = 0;
 3623 if (!m_isRobustnessEXTSupported) {
 3624 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
 3625 if (error != GraphicsContext3D::NO_ERROR) {
 3626 synthesizeGLError(error, "readPixels", "invalid dimensions");
 3627 return;
 3628 }
 3629 if (pixels->byteLength() < totalBytesRequired) {
 3630 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
 3631 return;
 3632 }
 3633 }
 3634
 3635 clearIfComposited();
 3636 void* data = pixels->baseAddress();
 3637
 3638 {
 3639 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 3640 if (m_isRobustnessEXTSupported)
 3641 m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels->byteLength(), data);
 3642 else
 3643 m_context->readPixels(x, y, width, height, format, type, data);
 3644 }
 3645
 3646#if OS(DARWIN)
 3647 if (m_isRobustnessEXTSupported) // we haven't computed padding
 3648 m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
 3649 // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
 3650 // on QC is fixed, i.e., when alpha is off, readPixels should
 3651 // set alpha to 255 instead of 0.
 3652 if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
 3653 unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
 3654 for (GC3Dsizei iy = 0; iy < height; ++iy) {
 3655 for (GC3Dsizei ix = 0; ix < width; ++ix) {
 3656 pixels[3] = 255;
 3657 pixels += 4;
 3658 }
 3659 pixels += padding;
 3660 }
 3661 }
 3662#endif
 3663}
 3664
 3665void WebGLRenderingContext::releaseShaderCompiler()
 3666{
 3667 if (isContextLostOrPending())
 3668 return;
 3669 m_context->releaseShaderCompiler();
 3670}
 3671
 3672void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
 3673{
 3674 if (isContextLostOrPending())
 3675 return;
 3676 if (target != GraphicsContext3D::RENDERBUFFER) {
 3677 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
 3678 return;
 3679 }
 3680 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
 3681 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
 3682 return;
 3683 }
 3684 if (!validateSize("renderbufferStorage", width, height))
 3685 return;
 3686 switch (internalformat) {
 3687 case GraphicsContext3D::DEPTH_COMPONENT16:
 3688 case GraphicsContext3D::RGBA4:
 3689 case GraphicsContext3D::RGB5_A1:
 3690 case GraphicsContext3D::RGB565:
 3691 case GraphicsContext3D::STENCIL_INDEX8:
 3692 case Extensions3D::SRGB8_ALPHA8_EXT:
 3693 if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) {
 3694 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
 3695 return;
 3696 }
 3697 m_context->renderbufferStorage(target, internalformat, width, height);
 3698 m_renderbufferBinding->setInternalFormat(internalformat);
 3699 m_renderbufferBinding->setIsValid(true);
 3700 m_renderbufferBinding->setSize(width, height);
 3701 break;
 3702 case GraphicsContext3D::DEPTH_STENCIL:
 3703 if (isDepthStencilSupported()) {
 3704 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
 3705 }
 3706 m_renderbufferBinding->setSize(width, height);
 3707 m_renderbufferBinding->setIsValid(isDepthStencilSupported());
 3708 m_renderbufferBinding->setInternalFormat(internalformat);
 3709 break;
 3710 default:
 3711 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
 3712 return;
 3713 }
 3714 applyStencilTest();
 3715}
 3716
 3717void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
 3718{
 3719 if (isContextLostOrPending())
 3720 return;
 3721 m_context->sampleCoverage(value, invert);
 3722}
 3723
 3724void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 3725{
 3726 if (isContextLostOrPending())
 3727 return;
 3728 if (!validateSize("scissor", width, height))
 3729 return;
 3730 m_context->scissor(x, y, width, height);
 3731}
 3732
 3733void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
 3734{
 3735 UNUSED_PARAM(ec);
 3736 if (isContextLostOrPending() || !validateWebGLObject("shaderSource", shader))
 3737 return;
 3738 String stringWithoutComments = StripComments(string).result();
 3739 if (!validateString("shaderSource", stringWithoutComments))
 3740 return;
 3741 shader->setSource(string);
 3742 m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
 3743}
 3744
 3745void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
 3746{
 3747 if (isContextLostOrPending())
 3748 return;
 3749 if (!validateStencilFunc("stencilFunc", func))
 3750 return;
 3751 m_stencilFuncRef = ref;
 3752 m_stencilFuncRefBack = ref;
 3753 m_stencilFuncMask = mask;
 3754 m_stencilFuncMaskBack = mask;
 3755 m_context->stencilFunc(func, ref, mask);
 3756}
 3757
 3758void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
 3759{
 3760 if (isContextLostOrPending())
 3761 return;
 3762 if (!validateStencilFunc("stencilFuncSeparate", func))
 3763 return;
 3764 switch (face) {
 3765 case GraphicsContext3D::FRONT_AND_BACK:
 3766 m_stencilFuncRef = ref;
 3767 m_stencilFuncRefBack = ref;
 3768 m_stencilFuncMask = mask;
 3769 m_stencilFuncMaskBack = mask;
 3770 break;
 3771 case GraphicsContext3D::FRONT:
 3772 m_stencilFuncRef = ref;
 3773 m_stencilFuncMask = mask;
 3774 break;
 3775 case GraphicsContext3D::BACK:
 3776 m_stencilFuncRefBack = ref;
 3777 m_stencilFuncMaskBack = mask;
 3778 break;
 3779 default:
 3780 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face");
 3781 return;
 3782 }
 3783 m_context->stencilFuncSeparate(face, func, ref, mask);
 3784}
 3785
 3786void WebGLRenderingContext::stencilMask(GC3Duint mask)
 3787{
 3788 if (isContextLostOrPending())
 3789 return;
 3790 m_stencilMask = mask;
 3791 m_stencilMaskBack = mask;
 3792 m_context->stencilMask(mask);
 3793}
 3794
 3795void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
 3796{
 3797 if (isContextLostOrPending())
 3798 return;
 3799 switch (face) {
 3800 case GraphicsContext3D::FRONT_AND_BACK:
 3801 m_stencilMask = mask;
 3802 m_stencilMaskBack = mask;
 3803 break;
 3804 case GraphicsContext3D::FRONT:
 3805 m_stencilMask = mask;
 3806 break;
 3807 case GraphicsContext3D::BACK:
 3808 m_stencilMaskBack = mask;
 3809 break;
 3810 default:
 3811 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face");
 3812 return;
 3813 }
 3814 m_context->stencilMaskSeparate(face, mask);
 3815}
 3816
 3817void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
 3818{
 3819 if (isContextLostOrPending())
 3820 return;
 3821 m_context->stencilOp(fail, zfail, zpass);
 3822}
 3823
 3824void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
 3825{
 3826 if (isContextLostOrPending())
 3827 return;
 3828 m_context->stencilOpSeparate(face, fail, zfail, zpass);
 3829}
 3830
 3831void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
 3832{
 3833 // FIXME: For now we ignore any errors returned.
 3834 ec = 0;
 3835 WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
 3836 ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type));
 3837 ASSERT(tex);
 3838 ASSERT(!level || !WebGLTexture::isNPOT(width, height));
 3839 if (!pixels) {
 3840 // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true.
 3841 // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures
 3842 // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
 3843 // clear.
 3844 if (isResourceSafe())
 3845 m_context->texImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
 3846 else {
 3847 bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
 3848 border, format, type, m_unpackAlignment);
 3849 if (!succeed)
 3850 return;
 3851 }
 3852 } else {
 3853 ASSERT(validateSettableTexFormat("texImage2D", internalformat));
 3854 m_context->moveErrorsToSyntheticErrorList();
 3855 m_context->texImage2D(target, level, internalformat, width, height,
 3856 border, format, type, pixels);
 3857 if (m_context->moveErrorsToSyntheticErrorList()) {
 3858 // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
 3859 tex->markInvalid(target, level);
 3860 return;
 3861 }
 3862 }
 3863 tex->setLevelInfo(target, level, internalformat, width, height, type);
 3864}
 3865
 3866void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
 3867{
 3868 ec = 0;
 3869 Vector<uint8_t> data;
 3870 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
 3871 if (!imageExtractor.extractSucceeded()) {
 3872 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
 3873 return;
 3874 }
 3875 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
 3876 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
 3877 const void* imagePixelData = imageExtractor.imagePixelData();
 3878
 3879 bool needConversion = true;
 3880 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
 3881 needConversion = false;
 3882 else {
 3883 if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
 3884 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error");
 3885 return;
 3886 }
 3887 }
 3888
 3889 if (m_unpackAlignment != 1)
 3890 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 3891 texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, ec);
 3892 if (m_unpackAlignment != 1)
 3893 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 3894}
 3895
 3896bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset)
 3897{
 3898 if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type))
 3899 return false;
 3900
 3901 WebGLTexture* texture = validateTextureBinding(functionName, target, true);
 3902 if (!texture)
 3903 return false;
 3904
 3905 if (functionType == NotTexSubImage2D) {
 3906 if (level && WebGLTexture::isNPOT(width, height)) {
 3907 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2");
 3908 return false;
 3909 }
 3910 // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
 3911 // by checking if the ArrayBufferView is null or not.
 3912 if (sourceType != SourceArrayBufferView) {
 3913 if (!validateSettableTexFormat(functionName, format))
 3914 return false;
 3915 }
 3916 } else {
 3917 if (!validateSettableTexFormat(functionName, format))
 3918 return false;
 3919 if (!validateSize(functionName, xoffset, yoffset))
 3920 return false;
 3921 // Before checking if it is in the range, check if overflow happens first.
 3922 if (xoffset + width < 0 || yoffset + height < 0) {
 3923 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "bad dimensions");
 3924 return false;
 3925 }
 3926 if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) {
 3927 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
 3928 return false;
 3929 }
 3930 if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) {
 3931 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
 3932 return false;
 3933 }
 3934 }
 3935
 3936 return true;
 3937}
 3938
 3939void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 3940 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 3941 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
 3942{
 3943 if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed)
 3944 || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
 3945 return;
 3946 void* data = pixels ? pixels->baseAddress() : 0;
 3947 Vector<uint8_t> tempData;
 3948 bool changeUnpackAlignment = false;
 3949 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
 3950 if (!m_context->extractTextureData(width, height, format, type,
 3951 m_unpackAlignment,
 3952 m_unpackFlipY, m_unpackPremultiplyAlpha,
 3953 data,
 3954 tempData))
 3955 return;
 3956 data = tempData.data();
 3957 changeUnpackAlignment = true;
 3958 }
 3959 if (changeUnpackAlignment)
 3960 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 3961 texImage2DBase(target, level, internalformat, width, height, border,
 3962 format, type, data, ec);
 3963 if (changeUnpackAlignment)
 3964 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 3965}
 3966
 3967void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 3968 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
 3969{
 3970 ec = 0;
 3971 if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
 3972 return;
 3973 Vector<uint8_t> data;
 3974 bool needConversion = true;
 3975 // The data from ImageData is always of format RGBA8.
 3976 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
 3977 if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
 3978 needConversion = false;
 3979 else {
 3980 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
 3981 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
 3982 return;
 3983 }
 3984 }
 3985 if (m_unpackAlignment != 1)
 3986 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 3987 texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
 3988 if (m_unpackAlignment != 1)
 3989 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 3990}
 3991
 3992PassRefPtr<Image> WebGLRenderingContext::drawImageIntoBuffer(Image* image, int width, int height, int deviceScaleFactor)
 3993{
 3994 IntSize size(width, height);
 3995 size.scale(deviceScaleFactor);
 3996 ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
 3997 if (!buf) {
 3998 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
 3999 return nullptr;
 4000 }
 4001
 4002 FloatRect srcRect(FloatPoint(), image->size());
 4003 FloatRect destRect(FloatPoint(), size);
 4004 buf->context()->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect);
 4005 return buf->copyImage(ImageBuffer::fastCopyImageMode());
 4006}
 4007
 4008void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 4009 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
 4010{
 4011 ec = 0;
 4012 if (isContextLostOrPending() || !validateHTMLImageElement("texImage2D", image, ec))
 4013 return;
 4014
 4015 RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
 4016 if (imageForRender->isSVGImage())
 4017 imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
 4018
 4019 if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
 4020 return;
 4021
 4022 texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4023}
 4024
 4025void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 4026 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
 4027{
 4028 ec = 0;
 4029 if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
 4030 return;
 4031
 4032 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
 4033 // If possible, copy from the canvas element directly to the texture
 4034 // via the GPU, without a read-back to system memory.
 4035 //
 4036 // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when
 4037 // ImageBuffer::copyToPlatformTexture implementations are fully functional.
 4038 if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level)
 4039 && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) && type == GraphicsContext3D::UNSIGNED_BYTE) {
 4040 ImageBuffer* buffer = canvas->buffer();
 4041 if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
 4042 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
 4043 return;
 4044 }
 4045 }
 4046
 4047 RefPtr<ImageData> imageData = canvas->getImageData();
 4048 if (imageData)
 4049 texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
 4050 else
 4051 texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4052}
 4053
 4054#if ENABLE(VIDEO)
 4055PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy, ExceptionCode&)
 4056{
 4057 IntSize size(video->videoWidth(), video->videoHeight());
 4058 ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
 4059 if (!buf) {
 4060 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
 4061 return nullptr;
 4062 }
 4063 IntRect destRect(0, 0, size.width(), size.height());
 4064 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
 4065 video->paintCurrentFrameInContext(buf->context(), destRect);
 4066 return buf->copyImage(backingStoreCopy);
 4067}
 4068
 4069void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 4070 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
 4071{
 4072 ec = 0;
 4073 if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video, ec)
 4074 || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
 4075 return;
 4076
 4077 // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
 4078 // Otherwise, it will fall back to the normal SW path.
 4079 // FIXME: The current restrictions require that format shoud be RGB or RGBA,
 4080 // type should be UNSIGNED_BYTE and level should be 0. It may be lifted in the future.
 4081 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
 4082 if (GraphicsContext3D::TEXTURE_2D == target && texture
 4083 && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
 4084 && type == GraphicsContext3D::UNSIGNED_BYTE
 4085 && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level))
 4086 && !level) {
 4087 if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
 4088 texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
 4089 return;
 4090 }
 4091 }
 4092
 4093 // Normal pure SW path.
 4094 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
 4095 if (!image)
 4096 return;
 4097 texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4098}
 4099#endif
 4100
 4101void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
 4102{
 4103 if (isContextLostOrPending())
 4104 return;
 4105 WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
 4106 if (!tex)
 4107 return;
 4108 switch (pname) {
 4109 case GraphicsContext3D::TEXTURE_MIN_FILTER:
 4110 case GraphicsContext3D::TEXTURE_MAG_FILTER:
 4111 break;
 4112 case GraphicsContext3D::TEXTURE_WRAP_S:
 4113 case GraphicsContext3D::TEXTURE_WRAP_T:
 4114 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
 4115 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
 4116 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter");
 4117 return;
 4118 }
 4119 break;
 4120 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
 4121 if (!m_extTextureFilterAnisotropic) {
 4122 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled");
 4123 return;
 4124 }
 4125 break;
 4126 default:
 4127 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name");
 4128 return;
 4129 }
 4130 if (isFloat) {
 4131 tex->setParameterf(pname, paramf);
 4132 m_context->texParameterf(target, pname, paramf);
 4133 } else {
 4134 tex->setParameteri(pname, parami);
 4135 m_context->texParameteri(target, pname, parami);
 4136 }
 4137}
 4138
 4139void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
 4140{
 4141 texParameter(target, pname, param, 0, true);
 4142}
 4143
 4144void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
 4145{
 4146 texParameter(target, pname, 0, param, false);
 4147}
 4148
 4149void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
 4150{
 4151 // FIXME: For now we ignore any errors returned
 4152 ec = 0;
 4153 ASSERT(!isContextLost());
 4154 ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type));
 4155 ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
 4156 ASSERT(validateSettableTexFormat("texSubImage2D", format));
 4157 WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
 4158 if (!tex) {
 4159 ASSERT_NOT_REACHED();
 4160 return;
 4161 }
 4162 ASSERT((xoffset + width) >= 0);
 4163 ASSERT((yoffset + height) >= 0);
 4164 ASSERT(tex->getWidth(target, level) >= (xoffset + width));
 4165 ASSERT(tex->getHeight(target, level) >= (yoffset + height));
 4166 ASSERT(tex->getInternalFormat(target, level) == format);
 4167 ASSERT(tex->getType(target, level) == type);
 4168 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 4169}
 4170
 4171void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
 4172{
 4173 ec = 0;
 4174 Vector<uint8_t> data;
 4175 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
 4176 if (!imageExtractor.extractSucceeded()) {
 4177 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
 4178 return;
 4179 }
 4180 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
 4181 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
 4182 const void* imagePixelData = imageExtractor.imagePixelData();
 4183
 4184 bool needConversion = true;
 4185 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
 4186 needConversion = false;
 4187 else {
 4188 if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
 4189 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
 4190 return;
 4191 }
 4192 }
 4193
 4194 if (m_unpackAlignment != 1)
 4195 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4196 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, ec);
 4197 if (m_unpackAlignment != 1)
 4198 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4199}
 4200
 4201void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4202 GC3Dsizei width, GC3Dsizei height,
 4203 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
 4204{
 4205 if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed)
 4206 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
 4207 return;
 4208 void* data = pixels->baseAddress();
 4209 Vector<uint8_t> tempData;
 4210 bool changeUnpackAlignment = false;
 4211 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
 4212 if (!m_context->extractTextureData(width, height, format, type,
 4213 m_unpackAlignment,
 4214 m_unpackFlipY, m_unpackPremultiplyAlpha,
 4215 data,
 4216 tempData))
 4217 return;
 4218 data = tempData.data();
 4219 changeUnpackAlignment = true;
 4220 }
 4221 if (changeUnpackAlignment)
 4222 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4223 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
 4224 if (changeUnpackAlignment)
 4225 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4226}
 4227
 4228void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4229 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
 4230{
 4231 ec = 0;
 4232 if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
 4233 return;
 4234
 4235 Vector<uint8_t> data;
 4236 bool needConversion = true;
 4237 // The data from ImageData is always of format RGBA8.
 4238 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
 4239 if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
 4240 needConversion = false;
 4241 else {
 4242 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
 4243 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
 4244 return;
 4245 }
 4246 }
 4247 if (m_unpackAlignment != 1)
 4248 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4249 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
 4250 if (m_unpackAlignment != 1)
 4251 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4252}
 4253
 4254void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4255 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
 4256{
 4257 ec = 0;
 4258 if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
 4259 return;
 4260
 4261 RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
 4262 if (imageForRender->isSVGImage())
 4263 imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
 4264
 4265 if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
 4266 return;
 4267
 4268 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4269}
 4270
 4271void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4272 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
 4273{
 4274 ec = 0;
 4275 if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
 4276 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
 4277 return;
 4278
 4279 RefPtr<ImageData> imageData = canvas->getImageData();
 4280 if (imageData)
 4281 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
 4282 else
 4283 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4284}
 4285
 4286#if ENABLE(VIDEO)
 4287void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4288 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
 4289{
 4290 ec = 0;
 4291 if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
 4292 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
 4293 return;
 4294
 4295 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
 4296 if (!image)
 4297 return;
 4298 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4299}
 4300#endif
 4301
 4302void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
 4303{
 4304 UNUSED_PARAM(ec);
 4305 if (isContextLostOrPending() || !location)
 4306 return;
 4307
 4308 if (location->program() != m_currentProgram) {
 4309 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program");
 4310 return;
 4311 }
 4312
 4313 m_context->uniform1f(location->location(), x);
 4314}
 4315
 4316void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4317{
 4318 UNUSED_PARAM(ec);
 4319 if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, 1))
 4320 return;
 4321
 4322 m_context->uniform1fv(location->location(), v->length(), v->data());
 4323}
 4324
 4325void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4326{
 4327 UNUSED_PARAM(ec);
 4328 if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, size, 1))
 4329 return;
 4330
 4331 m_context->uniform1fv(location->location(), size, v);
 4332}
 4333
 4334void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
 4335{
 4336 UNUSED_PARAM(ec);
 4337 if (isContextLostOrPending() || !location)
 4338 return;
 4339
 4340 if (location->program() != m_currentProgram) {
 4341 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program");
 4342 return;
 4343 }
 4344
 4345 if ((location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) && x >= (int)m_textureUnits.size()) {
 4346 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1i", "invalid texture unit");
 4347 return;
 4348 }
 4349
 4350 m_context->uniform1i(location->location(), x);
 4351}
 4352
 4353void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4354{
 4355 UNUSED_PARAM(ec);
 4356 if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, 1))
 4357 return;
 4358
 4359 if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE)
 4360 for (unsigned i = 0; i < v->length(); ++i) {
 4361 if (v->data()[i] >= static_cast<int>(m_textureUnits.size())) {
 4362 LOG(WebGL, "Texture unit size=%zu, v[%d]=%d. Location type = %04X.", m_textureUnits.size(), i, v->data()[i], location->type());
 4363 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
 4364 return;
 4365 }
 4366 }
 4367
 4368 m_context->uniform1iv(location->location(), v->length(), v->data());
 4369}
 4370
 4371void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4372{
 4373 UNUSED_PARAM(ec);
 4374 if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, size, 1))
 4375 return;
 4376
 4377 if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE)
 4378 for (unsigned i = 0; i < static_cast<unsigned>(size); ++i) {
 4379 if (((GC3Dint*)v)[i] >= static_cast<int>(m_textureUnits.size())) {
 4380 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
 4381 return;
 4382 }
 4383 }
 4384
 4385 m_context->uniform1iv(location->location(), size, v);
 4386}
 4387
 4388void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
 4389{
 4390 UNUSED_PARAM(ec);
 4391 if (isContextLostOrPending() || !location)
 4392 return;
 4393
 4394 if (location->program() != m_currentProgram) {
 4395 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program");
 4396 return;
 4397 }
 4398
 4399 m_context->uniform2f(location->location(), x, y);
 4400}
 4401
 4402void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4403{
 4404 UNUSED_PARAM(ec);
 4405 if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, 2))
 4406 return;
 4407
 4408 m_context->uniform2fv(location->location(), v->length() / 2, v->data());
 4409}
 4410
 4411void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4412{
 4413 UNUSED_PARAM(ec);
 4414 if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, size, 2))
 4415 return;
 4416
 4417 m_context->uniform2fv(location->location(), size / 2, v);
 4418}
 4419
 4420void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
 4421{
 4422 UNUSED_PARAM(ec);
 4423 if (isContextLostOrPending() || !location)
 4424 return;
 4425
 4426 if (location->program() != m_currentProgram) {
 4427 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program");
 4428 return;
 4429 }
 4430
 4431 m_context->uniform2i(location->location(), x, y);
 4432}
 4433
 4434void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4435{
 4436 UNUSED_PARAM(ec);
 4437 if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, 2))
 4438 return;
 4439
 4440 m_context->uniform2iv(location->location(), v->length() / 2, v->data());
 4441}
 4442
 4443void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4444{
 4445 UNUSED_PARAM(ec);
 4446 if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, size, 2))
 4447 return;
 4448
 4449 m_context->uniform2iv(location->location(), size / 2, v);
 4450}
 4451
 4452void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
 4453{
 4454 UNUSED_PARAM(ec);
 4455 if (isContextLostOrPending() || !location)
 4456 return;
 4457
 4458 if (location->program() != m_currentProgram) {
 4459 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program");
 4460 return;
 4461 }
 4462
 4463 m_context->uniform3f(location->location(), x, y, z);
 4464}
 4465
 4466void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4467{
 4468 UNUSED_PARAM(ec);
 4469 if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, 3))
 4470 return;
 4471
 4472 m_context->uniform3fv(location->location(), v->length() / 3, v->data());
 4473}
 4474
 4475void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4476{
 4477 UNUSED_PARAM(ec);
 4478 if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, size, 3))
 4479 return;
 4480
 4481 m_context->uniform3fv(location->location(), size / 3, v);
 4482}
 4483
 4484void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
 4485{
 4486 UNUSED_PARAM(ec);
 4487 if (isContextLostOrPending() || !location)
 4488 return;
 4489
 4490 if (location->program() != m_currentProgram) {
 4491 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program");
 4492 return;
 4493 }
 4494
 4495 m_context->uniform3i(location->location(), x, y, z);
 4496}
 4497
 4498void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4499{
 4500 UNUSED_PARAM(ec);
 4501 if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, 3))
 4502 return;
 4503
 4504 m_context->uniform3iv(location->location(), v->length() / 3, v->data());
 4505}
 4506
 4507void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4508{
 4509 UNUSED_PARAM(ec);
 4510 if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, size, 3))
 4511 return;
 4512
 4513 m_context->uniform3iv(location->location(), size / 3, v);
 4514}
 4515
 4516void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
 4517{
 4518 UNUSED_PARAM(ec);
 4519 if (isContextLostOrPending() || !location)
 4520 return;
 4521
 4522 if (location->program() != m_currentProgram) {
 4523 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program");
 4524 return;
 4525 }
 4526
 4527 m_context->uniform4f(location->location(), x, y, z, w);
 4528}
 4529
 4530void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4531{
 4532 UNUSED_PARAM(ec);
 4533 if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, 4))
 4534 return;
 4535
 4536 m_context->uniform4fv(location->location(), v->length() / 4, v->data());
 4537}
 4538
 4539void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4540{
 4541 UNUSED_PARAM(ec);
 4542 if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, size, 4))
 4543 return;
 4544
 4545 m_context->uniform4fv(location->location(), size / 4, v);
 4546}
 4547
 4548void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
 4549{
 4550 UNUSED_PARAM(ec);
 4551 if (isContextLostOrPending() || !location)
 4552 return;
 4553
 4554 if (location->program() != m_currentProgram) {
 4555 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program");
 4556 return;
 4557 }
 4558
 4559 m_context->uniform4i(location->location(), x, y, z, w);
 4560}
 4561
 4562void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4563{
 4564 UNUSED_PARAM(ec);
 4565 if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, 4))
 4566 return;
 4567
 4568 m_context->uniform4iv(location->location(), v->length() / 4, v->data());
 4569}
 4570
 4571void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4572{
 4573 UNUSED_PARAM(ec);
 4574 if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, size, 4))
 4575 return;
 4576
 4577 m_context->uniform4iv(location->location(), size / 4, v);
 4578}
 4579
 4580void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
 4581{
 4582 UNUSED_PARAM(ec);
 4583 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
 4584 return;
 4585 m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data());
 4586}
 4587
 4588void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4589{
 4590 UNUSED_PARAM(ec);
 4591 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
 4592 return;
 4593 m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
 4594}
 4595
 4596void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
 4597{
 4598 UNUSED_PARAM(ec);
 4599 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
 4600 return;
 4601 m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data());
 4602}
 4603
 4604void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4605{
 4606 UNUSED_PARAM(ec);
 4607 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
 4608 return;
 4609 m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
 4610}
 4611
 4612void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
 4613{
 4614 UNUSED_PARAM(ec);
 4615 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
 4616 return;
 4617 m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data());
 4618}
 4619
 4620void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4621{
 4622 UNUSED_PARAM(ec);
 4623 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
 4624 return;
 4625 m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
 4626}
 4627
 4628void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
 4629{
 4630 UNUSED_PARAM(ec);
 4631 bool deleted;
 4632 if (!checkObjectToBeBound("useProgram", program, deleted))
 4633 return;
 4634 if (deleted)
 4635 program = 0;
 4636 if (program && !program->getLinkStatus()) {
 4637 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid");
 4638 return;
 4639 }
 4640 if (m_currentProgram != program) {
 4641 if (m_currentProgram)
 4642 m_currentProgram->onDetached(graphicsContext3D());
 4643 m_currentProgram = program;
 4644 m_context->useProgram(objectOrZero(program));
 4645 if (program)
 4646 program->onAttached();
 4647 }
 4648}
 4649
 4650void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
 4651{
 4652 UNUSED_PARAM(ec);
 4653 if (isContextLostOrPending() || !validateWebGLObject("validateProgram", program))
 4654 return;
 4655 m_context->validateProgram(objectOrZero(program));
 4656}
 4657
 4658void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
 4659{
 4660 vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
 4661}
 4662
 4663void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
 4664{
 4665 vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
 4666}
 4667
 4668void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4669{
 4670 vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
 4671}
 4672
 4673void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
 4674{
 4675 vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
 4676}
 4677
 4678void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
 4679{
 4680 vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
 4681}
 4682
 4683void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4684{
 4685 vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
 4686}
 4687
 4688void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
 4689{
 4690 vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
 4691}
 4692
 4693void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
 4694{
 4695 vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
 4696}
 4697
 4698void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4699{
 4700 vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
 4701}
 4702
 4703void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
 4704{
 4705 vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
 4706}
 4707
 4708void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
 4709{
 4710 vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
 4711}
 4712
 4713void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4714{
 4715 vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
 4716}
 4717
 4718void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
 4719{
 4720 UNUSED_PARAM(ec);
 4721 if (isContextLostOrPending())
 4722 return;
 4723 switch (type) {
 4724 case GraphicsContext3D::BYTE:
 4725 case GraphicsContext3D::UNSIGNED_BYTE:
 4726 case GraphicsContext3D::SHORT:
 4727 case GraphicsContext3D::UNSIGNED_SHORT:
 4728 case GraphicsContext3D::FLOAT:
 4729 break;
 4730 default:
 4731 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
 4732 return;
 4733 }
 4734 if (index >= m_maxVertexAttribs) {
 4735 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range");
 4736 return;
 4737 }
 4738 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
 4739 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset");
 4740 return;
 4741 }
 4742 if (!m_boundArrayBuffer) {
 4743 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER");
 4744 return;
 4745 }
 4746 // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
 4747 unsigned int typeSize = sizeInBytes(type);
 4748 if (!typeSize) {
 4749 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
 4750 return;
 4751 }
 4752 if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
 4753 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type");
 4754 return;
 4755 }
 4756 GC3Dsizei bytesPerElement = size * typeSize;
 4757
 4758 m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer);
 4759 m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
 4760}
 4761
 4762void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 4763{
 4764 if (isContextLostOrPending())
 4765 return;
 4766 if (!validateSize("viewport", width, height))
 4767 return;
 4768 m_context->viewport(x, y, width, height);
 4769}
 4770
 4771void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
 4772{
 4773 if (isContextLostOrPending()) {
 4774 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost");
 4775 return;
 4776 }
 4777
 4778 m_contextGroup->loseContextGroup(mode);
 4779}
 4780
 4781void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode)
 4782{
 4783 if (isContextLost())
 4784 return;
 4785
 4786 m_contextLost = true;
 4787 m_contextLostMode = mode;
 4788
 4789 if (mode == RealLostContext) {
 4790 // Inform the embedder that a lost context was received. In response, the embedder might
 4791 // decide to take action such as asking the user for permission to use WebGL again.
 4792 if (Frame* frame = canvas()->document().frame())
 4793 frame->loader().client().didLoseWebGLContext(m_context->getExtensions()->getGraphicsResetStatusARB());
 4794 }
 4795
 4796 detachAndRemoveAllObjects();
 4797
 4798 if (m_drawingBuffer) {
 4799 // Make absolutely sure we do not refer to an already-deleted texture or framebuffer.
 4800 m_drawingBuffer->setTexture2DBinding(0);
 4801 m_drawingBuffer->setFramebufferBinding(0);
 4802 }
 4803
 4804 // There is no direct way to clear errors from a GL implementation and
 4805 // looping until getError() becomes NO_ERROR might cause an infinite loop if
 4806 // the driver or context implementation had a bug. So, loop a reasonably
 4807 // large number of times to clear any existing errors.
 4808 for (int i = 0; i < 100; ++i) {
 4809 if (m_context->getError() == GraphicsContext3D::NO_ERROR)
 4810 break;
 4811 }
 4812 ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole;
 4813 synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost", display);
 4814
 4815 // Don't allow restoration unless the context lost event has both been
 4816 // dispatched and its default behavior prevented.
 4817 m_restoreAllowed = false;
 4818
 4819 // Always defer the dispatch of the context lost event, to implement
 4820 // the spec behavior of queueing a task.
 4821 m_dispatchContextLostEventTimer.startOneShot(0);
 4822}
 4823
 4824void WebGLRenderingContext::forceRestoreContext()
 4825{
 4826 if (!isContextLostOrPending()) {
 4827 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost");
 4828 return;
 4829 }
 4830
 4831 if (!m_restoreAllowed) {
 4832 if (m_contextLostMode == SyntheticLostContext)
 4833 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed");
 4834 return;
 4835 }
 4836
 4837 if (!m_restoreTimer.isActive())
 4838 m_restoreTimer.startOneShot(0);
 4839}
 4840
 4841PlatformLayer* WebGLRenderingContext::platformLayer() const
 4842{
 4843 return (!isContextLost() && !m_isPendingPolicyResolution) ? m_context->platformLayer() : 0;
 4844}
 4845
 4846void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
 4847{
 4848 if (m_isPendingPolicyResolution)
 4849 return;
 4850
 4851 m_contextGroup->removeObject(object);
 4852}
 4853
 4854void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object)
 4855{
 4856 if (m_isPendingPolicyResolution)
 4857 return;
 4858
 4859 ASSERT(!isContextLost());
 4860 m_contextGroup->addObject(object);
 4861}
 4862
 4863void WebGLRenderingContext::removeContextObject(WebGLContextObject* object)
 4864{
 4865 if (m_isPendingPolicyResolution)
 4866 return;
 4867
 4868 m_contextObjects.remove(object);
 4869}
 4870
 4871void WebGLRenderingContext::addContextObject(WebGLContextObject* object)
 4872{
 4873 if (m_isPendingPolicyResolution)
 4874 return;
 4875
 4876 ASSERT(!isContextLost());
 4877 m_contextObjects.add(object);
 4878}
 4879
 4880void WebGLRenderingContext::detachAndRemoveAllObjects()
 4881{
 4882 if (m_isPendingPolicyResolution)
 4883 return;
 4884
 4885 while (m_contextObjects.size() > 0) {
 4886 HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
 4887 (*it)->detachContext();
 4888 }
 4889}
 4890
 4891bool WebGLRenderingContext::hasPendingActivity() const
 4892{
 4893 return false;
 4894}
 4895
 4896void WebGLRenderingContext::stop()
 4897{
 4898 if (!isContextLost() && !m_isPendingPolicyResolution) {
 4899 forceLostContext(SyntheticLostContext);
 4900 destroyGraphicsContext3D();
 4901 }
 4902}
 4903
 4904WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
 4905{
 4906 GC3Dboolean value = 0;
 4907 m_context->getBooleanv(pname, &value);
 4908 return WebGLGetInfo(static_cast<bool>(value));
 4909}
 4910
 4911WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
 4912{
 4913 if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
 4914 notImplemented();
 4915 return WebGLGetInfo(0, 0);
 4916 }
 4917 GC3Dboolean value[4] = {0};
 4918 m_context->getBooleanv(pname, value);
 4919 bool boolValue[4];
 4920 for (int ii = 0; ii < 4; ++ii)
 4921 boolValue[ii] = static_cast<bool>(value[ii]);
 4922 return WebGLGetInfo(boolValue, 4);
 4923}
 4924
 4925WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
 4926{
 4927 GC3Dfloat value = 0;
 4928 m_context->getFloatv(pname, &value);
 4929 return WebGLGetInfo(value);
 4930}
 4931
 4932WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
 4933{
 4934 GC3Dint value = 0;
 4935 m_context->getIntegerv(pname, &value);
 4936 return WebGLGetInfo(value);
 4937}
 4938
 4939WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
 4940{
 4941 GC3Dint value = 0;
 4942 m_context->getIntegerv(pname, &value);
 4943 return WebGLGetInfo(static_cast<unsigned int>(value));
 4944}
 4945
 4946WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
 4947{
 4948 GC3Dfloat value[4] = {0};
 4949 m_context->getFloatv(pname, value);
 4950 unsigned length = 0;
 4951 switch (pname) {
 4952 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
 4953 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
 4954 case GraphicsContext3D::DEPTH_RANGE:
 4955 length = 2;
 4956 break;
 4957 case GraphicsContext3D::BLEND_COLOR:
 4958 case GraphicsContext3D::COLOR_CLEAR_VALUE:
 4959 length = 4;
 4960 break;
 4961 default:
 4962 notImplemented();
 4963 }
 4964 return WebGLGetInfo(Float32Array::create(value, length));
 4965}
 4966
 4967WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
 4968{
 4969 GC3Dint value[4] = {0};
 4970 m_context->getIntegerv(pname, value);
 4971 unsigned length = 0;
 4972 switch (pname) {
 4973 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
 4974 length = 2;
 4975 break;
 4976 case GraphicsContext3D::SCISSOR_BOX:
 4977 case GraphicsContext3D::VIEWPORT:
 4978 length = 4;
 4979 break;
 4980 default:
 4981 notImplemented();
 4982 }
 4983 return WebGLGetInfo(Int32Array::create(value, length));
 4984}
 4985
 4986void WebGLRenderingContext::checkTextureCompleteness(const char* functionName, bool prepareToDraw)
 4987{
 4988 bool resetActiveUnit = false;
 4989 WebGLTexture::TextureExtensionFlag extensions = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0));
 4990
 4991 for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
 4992 if ((m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
 4993 || (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))) {
 4994 if (ii != m_activeTextureUnit) {
 4995 m_context->activeTexture(ii);
 4996 resetActiveUnit = true;
 4997 } else if (resetActiveUnit) {
 4998 m_context->activeTexture(ii);
 4999 resetActiveUnit = false;
 5000 }
 5001 WebGLTexture* tex2D;
 5002 WebGLTexture* texCubeMap;
 5003 if (prepareToDraw) {
 5004 String msg(String("texture bound to texture unit ") + String::number(ii)
 5005 + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete',"
 5006 + " or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled.");
 5007 printGLWarningToConsole(functionName, msg.utf8().data());
 5008 tex2D = m_blackTexture2D.get();
 5009 texCubeMap = m_blackTextureCubeMap.get();
 5010 } else {
 5011 tex2D = m_textureUnits[ii].texture2DBinding.get();
 5012 texCubeMap = m_textureUnits[ii].textureCubeMapBinding.get();
 5013 }
 5014 if (m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
 5015 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
 5016 if (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))
 5017 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
 5018 }
 5019 }
 5020 if (resetActiveUnit)
 5021 m_context->activeTexture(m_activeTextureUnit);
 5022}
 5023
 5024void WebGLRenderingContext::createFallbackBlackTextures1x1()
 5025{
 5026 unsigned char black[] = {0, 0, 0, 255};
 5027 m_blackTexture2D = createTexture();
 5028 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
 5029 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
 5030 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5031 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
 5032 m_blackTextureCubeMap = createTexture();
 5033 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
 5034 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
 5035 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5036 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
 5037 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5038 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
 5039 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5040 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
 5041 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5042 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
 5043 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5044 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
 5045 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5046 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
 5047}
 5048
 5049bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
 5050 GC3Denum colorBufferFormat)
 5051{
 5052 unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
 5053 unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
 5054 return (need & have) == need;
 5055}
 5056
 5057GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
 5058{
 5059 if (m_framebufferBinding && m_framebufferBinding->object())
 5060 return m_framebufferBinding->getColorBufferFormat();
 5061 if (m_attributes.alpha)
 5062 return GraphicsContext3D::RGBA;
 5063 return GraphicsContext3D::RGB;
 5064}
 5065
 5066int WebGLRenderingContext::getBoundFramebufferWidth()
 5067{
 5068 if (m_framebufferBinding && m_framebufferBinding->object())
 5069 return m_framebufferBinding->getColorBufferWidth();
 5070 return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width();
 5071}
 5072
 5073int WebGLRenderingContext::getBoundFramebufferHeight()
 5074{
 5075 if (m_framebufferBinding && m_framebufferBinding->object())
 5076 return m_framebufferBinding->getColorBufferHeight();
 5077 return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height();
 5078}
 5079
 5080WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap)
 5081{
 5082 WebGLTexture* texture = nullptr;
 5083 switch (target) {
 5084 case GraphicsContext3D::TEXTURE_2D:
 5085 texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get();
 5086 break;
 5087 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
 5088 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
 5089 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
 5090 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
 5091 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
 5092 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
 5093 if (!useSixEnumsForCubeMap) {
 5094 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
 5095 return nullptr;
 5096 }
 5097 texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
 5098 break;
 5099 case GraphicsContext3D::TEXTURE_CUBE_MAP:
 5100 if (useSixEnumsForCubeMap) {
 5101 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
 5102 return nullptr;
 5103 }
 5104 texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
 5105 break;
 5106 default:
 5107 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
 5108 return nullptr;
 5109 }
 5110 if (!texture)
 5111 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture");
 5112 return texture;
 5113}
 5114
 5115bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string)
 5116{
 5117 const unsigned maxWebGLLocationLength = 256;
 5118 if (string.length() > maxWebGLLocationLength) {
 5119 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256");
 5120 return false;
 5121 }
 5122 return true;
 5123}
 5124
 5125bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y)
 5126{
 5127 if (x < 0 || y < 0) {
 5128 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
 5129 return false;
 5130 }
 5131 return true;
 5132}
 5133
 5134bool WebGLRenderingContext::validateString(const char* functionName, const String& string)
 5135{
 5136 for (size_t i = 0; i < string.length(); ++i) {
 5137 if (!validateCharacter(string[i])) {
 5138 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII");
 5139 return false;
 5140 }
 5141 }
 5142 return true;
 5143}
 5144
 5145bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
 5146{
 5147 switch (format) {
 5148 case GraphicsContext3D::ALPHA:
 5149 case GraphicsContext3D::LUMINANCE:
 5150 case GraphicsContext3D::LUMINANCE_ALPHA:
 5151 case GraphicsContext3D::RGB:
 5152 case GraphicsContext3D::RGBA:
 5153 break;
 5154 case GraphicsContext3D::DEPTH_STENCIL:
 5155 case GraphicsContext3D::DEPTH_COMPONENT:
 5156 if (m_webglDepthTexture)
 5157 break;
 5158 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
 5159 return false;
 5160 case Extensions3D::SRGB_EXT:
 5161 case Extensions3D::SRGB_ALPHA_EXT:
 5162 default:
 5163 if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
 5164 && m_extsRGB)
 5165 break;
 5166 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
 5167 return false;
 5168 }
 5169
 5170 switch (type) {
 5171 case GraphicsContext3D::UNSIGNED_BYTE:
 5172 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
 5173 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
 5174 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
 5175 break;
 5176 case GraphicsContext3D::FLOAT:
 5177 if (m_oesTextureFloat)
 5178 break;
 5179 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5180 return false;
 5181 case GraphicsContext3D::HALF_FLOAT_OES:
 5182 if (m_oesTextureHalfFloat)
 5183 break;
 5184 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5185 return false;
 5186 case GraphicsContext3D::UNSIGNED_INT:
 5187 case GraphicsContext3D::UNSIGNED_INT_24_8:
 5188 case GraphicsContext3D::UNSIGNED_SHORT:
 5189 if (m_webglDepthTexture)
 5190 break;
 5191 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5192 return false;
 5193 default:
 5194 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5195 return false;
 5196 }
 5197
 5198 // Verify that the combination of format and type is supported.
 5199 switch (format) {
 5200 case GraphicsContext3D::ALPHA:
 5201 case GraphicsContext3D::LUMINANCE:
 5202 case GraphicsContext3D::LUMINANCE_ALPHA:
 5203 if (type != GraphicsContext3D::UNSIGNED_BYTE
 5204 && type != GraphicsContext3D::FLOAT
 5205 && type != GraphicsContext3D::HALF_FLOAT_OES) {
 5206 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
 5207 return false;
 5208 }
 5209 break;
 5210 case GraphicsContext3D::RGB:
 5211 case Extensions3D::SRGB_EXT:
 5212 if (type != GraphicsContext3D::UNSIGNED_BYTE
 5213 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
 5214 && type != GraphicsContext3D::FLOAT
 5215 && type != GraphicsContext3D::HALF_FLOAT_OES) {
 5216 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
 5217 return false;
 5218 }
 5219 break;
 5220 case GraphicsContext3D::RGBA:
 5221 case Extensions3D::SRGB_ALPHA_EXT:
 5222 if (type != GraphicsContext3D::UNSIGNED_BYTE
 5223 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
 5224 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
 5225 && type != GraphicsContext3D::FLOAT
 5226 && type != GraphicsContext3D::HALF_FLOAT_OES) {
 5227 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
 5228 return false;
 5229 }
 5230 break;
 5231 case GraphicsContext3D::DEPTH_COMPONENT:
 5232 if (!m_webglDepthTexture) {
 5233 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
 5234 return false;
 5235 }
 5236 if (type != GraphicsContext3D::UNSIGNED_SHORT
 5237 && type != GraphicsContext3D::UNSIGNED_INT) {
 5238 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
 5239 return false;
 5240 }
 5241 if (level > 0) {
 5242 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
 5243 return false;
 5244 }
 5245 break;
 5246 case GraphicsContext3D::DEPTH_STENCIL:
 5247 if (!m_webglDepthTexture) {
 5248 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
 5249 return false;
 5250 }
 5251 if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
 5252 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
 5253 return false;
 5254 }
 5255 if (level > 0) {
 5256 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
 5257 return false;
 5258 }
 5259 break;
 5260 default:
 5261 ASSERT_NOT_REACHED();
 5262 }
 5263
 5264 return true;
 5265}
 5266
 5267bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
 5268{
 5269 if (level < 0) {
 5270 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
 5271 return false;
 5272 }
 5273 switch (target) {
 5274 case GraphicsContext3D::TEXTURE_2D:
 5275 if (level >= m_maxTextureLevel) {
 5276 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
 5277 return false;
 5278 }
 5279 break;
 5280 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
 5281 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
 5282 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
 5283 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
 5284 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
 5285 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
 5286 if (level >= m_maxCubeMapTextureLevel) {
 5287 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
 5288 return false;
 5289 }
 5290 break;
 5291 }
 5292 // This function only checks if level is legal, so we return true and don't
 5293 // generate INVALID_ENUM if target is illegal.
 5294 return true;
 5295}
 5296
 5297bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
 5298 TexFuncValidationFunctionType functionType,
 5299 GC3Denum target, GC3Dint level,
 5300 GC3Denum internalformat,
 5301 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 5302 GC3Denum format, GC3Denum type)
 5303{
 5304 // We absolutely have to validate the format and type combination.
 5305 // The texImage2D entry points taking HTMLImage, etc. will produce
 5306 // temporary data based on this combination, so it must be legal.
 5307 if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
 5308 return false;
 5309
 5310 if (width < 0 || height < 0) {
 5311 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
 5312 return false;
 5313 }
 5314
 5315 GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
 5316 switch (target) {
 5317 case GraphicsContext3D::TEXTURE_2D:
 5318 if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
 5319 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
 5320 return false;
 5321 }
 5322 break;
 5323 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
 5324 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
 5325 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
 5326 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
 5327 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
 5328 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
 5329 if (functionType != TexSubImage2D && width != height) {
 5330 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
 5331 return false;
 5332 }
 5333 // No need to check height here. For texImage width == height.
 5334 // For texSubImage that will be checked when checking yoffset + height is in range.
 5335 if (width > maxTextureSizeForLevel) {
 5336 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
 5337 return false;
 5338 }
 5339 break;
 5340 default:
 5341 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
 5342 return false;
 5343 }
 5344
 5345 if (format != internalformat) {
 5346 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
 5347 return false;
 5348 }
 5349
 5350 if (border) {
 5351 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
 5352 return false;
 5353 }
 5354
 5355 return true;
 5356}
 5357
 5358bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
 5359 GC3Dsizei width, GC3Dsizei height,
 5360 GC3Denum format, GC3Denum type,
 5361 ArrayBufferView* pixels,
 5362 NullDisposition disposition)
 5363{
 5364 if (!pixels) {
 5365 if (disposition == NullAllowed)
 5366 return true;
 5367 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
 5368 return false;
 5369 }
 5370
 5371 if (!validateTexFuncFormatAndType(functionName, format, type, level))
 5372 return false;
 5373 if (!validateSettableTexFormat(functionName, format))
 5374 return false;
 5375
 5376 switch (type) {
 5377 case GraphicsContext3D::UNSIGNED_BYTE:
 5378 if (pixels->getType() != JSC::TypeUint8) {
 5379 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
 5380 return false;
 5381 }
 5382 break;
 5383 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
 5384 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
 5385 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
 5386 if (pixels->getType() != JSC::TypeUint16) {
 5387 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
 5388 return false;
 5389 }
 5390 break;
 5391 case GraphicsContext3D::FLOAT: // OES_texture_float
 5392 if (pixels->getType() != JSC::TypeFloat32) {
 5393 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
 5394 return false;
 5395 }
 5396 break;
 5397 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
 5398 // As per the specification, ArrayBufferView should be null when
 5399 // OES_texture_half_float is enabled.
 5400 if (pixels) {
 5401 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
 5402 return false;
 5403 }
 5404 break;
 5405 default:
 5406 ASSERT_NOT_REACHED();
 5407 }
 5408
 5409 unsigned int totalBytesRequired;
 5410 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
 5411 if (error != GraphicsContext3D::NO_ERROR) {
 5412 synthesizeGLError(error, functionName, "invalid texture dimensions");
 5413 return false;
 5414 }
 5415 if (pixels->byteLength() < totalBytesRequired) {
 5416 if (m_unpackAlignment != 1) {
 5417 error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
 5418 if (pixels->byteLength() == totalBytesRequired) {
 5419 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
 5420 return false;
 5421 }
 5422 }
 5423 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
 5424 return false;
 5425 }
 5426 return true;
 5427}
 5428
 5429bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format)
 5430{
 5431 return m_compressedTextureFormats.contains(format);
 5432}
 5433
 5434bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName,
 5435 GC3Dsizei width, GC3Dsizei height,
 5436 GC3Denum format, ArrayBufferView* pixels)
 5437{
 5438 if (!pixels) {
 5439 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
 5440 return false;
 5441 }
 5442 if (width < 0 || height < 0) {
 5443 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
 5444 return false;
 5445 }
 5446
 5447 unsigned int bytesRequired = 0;
 5448
 5449 switch (format) {
 5450 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
 5451 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
 5452 case Extensions3D::COMPRESSED_ATC_RGB_AMD:
 5453 {
 5454 const int kBlockSize = 8;
 5455 const int kBlockWidth = 4;
 5456 const int kBlockHeight = 4;
 5457 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
 5458 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
 5459 bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
 5460 }
 5461 break;
 5462 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
 5463 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
 5464 case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD:
 5465 case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
 5466 {
 5467 const int kBlockSize = 16;
 5468 const int kBlockWidth = 4;
 5469 const int kBlockHeight = 4;
 5470 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
 5471 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
 5472 bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
 5473 }
 5474 break;
 5475 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
 5476 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
 5477 {
 5478 const int kBlockSize = 8;
 5479 const int kBlockWidth = 8;
 5480 const int kBlockHeight = 8;
 5481 bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 4 + 7) / kBlockSize;
 5482 }
 5483 break;
 5484 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
 5485 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
 5486 {
 5487 const int kBlockSize = 8;
 5488 const int kBlockWidth = 16;
 5489 const int kBlockHeight = 8;
 5490 bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 2 + 7) / kBlockSize;
 5491 }
 5492 break;
 5493 default:
 5494 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format");
 5495 return false;
 5496 }
 5497
 5498 if (pixels->byteLength() != bytesRequired) {
 5499 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions");
 5500 return false;
 5501 }
 5502
 5503 return true;
 5504}
 5505
 5506bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format)
 5507{
 5508 switch (format) {
 5509 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
 5510 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
 5511 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
 5512 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
 5513 const GC3Dsizei kBlockWidth = 4;
 5514 const GC3Dsizei kBlockHeight = 4;
 5515 const GC3Dint maxTextureSize = target ? m_maxTextureSize : m_maxCubeMapTextureSize;
 5516 const GC3Dsizei maxCompressedDimension = maxTextureSize >> level;
 5517 bool widthValid = (level && width == 1) || (level && width == 2) || (!(width % kBlockWidth) && width <= maxCompressedDimension);
 5518 bool heightValid = (level && height == 1) || (level && height == 2) || (!(height % kBlockHeight) && height <= maxCompressedDimension);
 5519 if (!widthValid || !heightValid) {
 5520 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
 5521 return false;
 5522 }
 5523 return true;
 5524 }
 5525 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
 5526 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
 5527 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
 5528 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
 5529 // Height and width must be powers of 2.
 5530 if ((width & (width - 1)) || (height & (height - 1))) {
 5531 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
 5532 return false;
 5533 }
 5534 return true;
 5535 default:
 5536 return false;
 5537 }
 5538}
 5539
 5540bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 5541 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
 5542{
 5543 if (xoffset < 0 || yoffset < 0) {
 5544 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
 5545 return false;
 5546 }
 5547
 5548 switch (format) {
 5549 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
 5550 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
 5551 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
 5552 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
 5553 const int kBlockWidth = 4;
 5554 const int kBlockHeight = 4;
 5555 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
 5556 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4");
 5557 return false;
 5558 }
 5559 if (width - xoffset > tex->getWidth(target, level)
 5560 || height - yoffset > tex->getHeight(target, level)) {
 5561 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range");
 5562 return false;
 5563 }
 5564 return validateCompressedTexDimensions(functionName, target, level, width, height, format);
 5565 }
 5566 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
 5567 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
 5568 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
 5569 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
 5570 if (xoffset || yoffset) {
 5571 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset and yoffset must be zero");
 5572 return false;
 5573 }
 5574 if (width != tex->getWidth(target, level)
 5575 || height != tex->getHeight(target, level)) {
 5576 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions must match existing level");
 5577 return false;
 5578 }
 5579 return validateCompressedTexDimensions(functionName, target, level, width, height, format);
 5580 }
 5581 default:
 5582 return false;
 5583 }
 5584}
 5585
 5586bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode)
 5587{
 5588 switch (mode) {
 5589 case GraphicsContext3D::POINTS:
 5590 case GraphicsContext3D::LINE_STRIP:
 5591 case GraphicsContext3D::LINE_LOOP:
 5592 case GraphicsContext3D::LINES:
 5593 case GraphicsContext3D::TRIANGLE_STRIP:
 5594 case GraphicsContext3D::TRIANGLE_FAN:
 5595 case GraphicsContext3D::TRIANGLES:
 5596 return true;
 5597 default:
 5598 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode");
 5599 return false;
 5600 }
 5601}
 5602
 5603bool WebGLRenderingContext::validateStencilSettings(const char* functionName)
 5604{
 5605 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
 5606 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match");
 5607 return false;
 5608 }
 5609 return true;
 5610}
 5611
 5612bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Denum func)
 5613{
 5614 switch (func) {
 5615 case GraphicsContext3D::NEVER:
 5616 case GraphicsContext3D::LESS:
 5617 case GraphicsContext3D::LEQUAL:
 5618 case GraphicsContext3D::GREATER:
 5619 case GraphicsContext3D::GEQUAL:
 5620 case GraphicsContext3D::EQUAL:
 5621 case GraphicsContext3D::NOTEQUAL:
 5622 case GraphicsContext3D::ALWAYS:
 5623 return true;
 5624 default:
 5625 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function");
 5626 return false;
 5627 }
 5628}
 5629
 5630void WebGLRenderingContext::printGLErrorToConsole(const String& message)
 5631{
 5632 if (!m_numGLErrorsToConsoleAllowed)
 5633 return;
 5634
 5635 --m_numGLErrorsToConsoleAllowed;
 5636 printWarningToConsole(message);
 5637
 5638 if (!m_numGLErrorsToConsoleAllowed)
 5639 printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context.");
 5640}
 5641
 5642void WebGLRenderingContext::printWarningToConsole(const String& message)
 5643{
 5644 if (!canvas())
 5645 return;
 5646 canvas()->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Warning, message);
 5647}
 5648
 5649bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
 5650{
 5651 if (target != GraphicsContext3D::FRAMEBUFFER) {
 5652 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
 5653 return false;
 5654 }
 5655 switch (attachment) {
 5656 case GraphicsContext3D::COLOR_ATTACHMENT0:
 5657 case GraphicsContext3D::DEPTH_ATTACHMENT:
 5658 case GraphicsContext3D::STENCIL_ATTACHMENT:
 5659 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
 5660 break;
 5661 default:
 5662 if (m_webglDrawBuffers
 5663 && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
 5664 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
 5665 break;
 5666 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
 5667 return false;
 5668 }
 5669 return true;
 5670}
 5671
 5672bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
 5673{
 5674 switch (mode) {
 5675 case GraphicsContext3D::FUNC_ADD:
 5676 case GraphicsContext3D::FUNC_SUBTRACT:
 5677 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
 5678 case Extensions3D::MIN_EXT:
 5679 case Extensions3D::MAX_EXT:
 5680 if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) {
 5681 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
 5682 return false;
 5683 }
 5684 return true;
 5685 break;
 5686 default:
 5687 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
 5688 return false;
 5689 }
 5690}
 5691
 5692bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst)
 5693{
 5694 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
 5695 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
 5696 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
 5697 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
 5698 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst");
 5699 return false;
 5700 }
 5701 return true;
 5702}
 5703
 5704bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
 5705{
 5706 switch (cap) {
 5707 case GraphicsContext3D::BLEND:
 5708 case GraphicsContext3D::CULL_FACE:
 5709 case GraphicsContext3D::DEPTH_TEST:
 5710 case GraphicsContext3D::DITHER:
 5711 case GraphicsContext3D::POLYGON_OFFSET_FILL:
 5712 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
 5713 case GraphicsContext3D::SAMPLE_COVERAGE:
 5714 case GraphicsContext3D::SCISSOR_TEST:
 5715 case GraphicsContext3D::STENCIL_TEST:
 5716 return true;
 5717 default:
 5718 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
 5719 return false;
 5720 }
 5721}
 5722
 5723bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
 5724{
 5725 if (!v) {
 5726 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5727 return false;
 5728 }
 5729 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
 5730}
 5731
 5732bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
 5733{
 5734 if (!v) {
 5735 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5736 return false;
 5737 }
 5738 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
 5739}
 5740
 5741bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
 5742{
 5743 return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize);
 5744}
 5745
 5746bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
 5747{
 5748 if (!v) {
 5749 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5750 return false;
 5751 }
 5752 return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize);
 5753}
 5754
 5755bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
 5756{
 5757 if (!location)
 5758 return false;
 5759 if (location->program() != m_currentProgram) {
 5760 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program");
 5761 return false;
 5762 }
 5763 if (!v) {
 5764 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5765 return false;
 5766 }
 5767 if (transpose) {
 5768 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE");
 5769 return false;
 5770 }
 5771 if (size < requiredMinSize || (size % requiredMinSize)) {
 5772 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
 5773 return false;
 5774 }
 5775 return true;
 5776}
 5777
 5778WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage)
 5779{
 5780 WebGLBuffer* buffer = 0;
 5781 switch (target) {
 5782 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
 5783 buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
 5784 break;
 5785 case GraphicsContext3D::ARRAY_BUFFER:
 5786 buffer = m_boundArrayBuffer.get();
 5787 break;
 5788 default:
 5789 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
 5790 return nullptr;
 5791 }
 5792 if (!buffer) {
 5793 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer");
 5794 return nullptr;
 5795 }
 5796 switch (usage) {
 5797 case GraphicsContext3D::STREAM_DRAW:
 5798 case GraphicsContext3D::STATIC_DRAW:
 5799 case GraphicsContext3D::DYNAMIC_DRAW:
 5800 return buffer;
 5801 }
 5802 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage");
 5803 return nullptr;
 5804}
 5805
 5806bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionCode& ec)
 5807{
 5808 if (!image || !image->cachedImage()) {
 5809 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image");
 5810 return false;
 5811 }
 5812 const URL& url = image->cachedImage()->response().url();
 5813 if (url.isNull() || url.isEmpty() || !url.isValid()) {
 5814 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image");
 5815 return false;
 5816 }
 5817 if (wouldTaintOrigin(image)) {
 5818 ec = SECURITY_ERR;
 5819 return false;
 5820 }
 5821 return true;
 5822}
 5823
 5824bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionCode& ec)
 5825{
 5826 if (!canvas || !canvas->buffer()) {
 5827 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no canvas");
 5828 return false;
 5829 }
 5830 if (wouldTaintOrigin(canvas)) {
 5831 ec = SECURITY_ERR;
 5832 return false;
 5833 }
 5834 return true;
 5835}
 5836
 5837#if ENABLE(VIDEO)
 5838bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionCode& ec)
 5839{
 5840 if (!video || !video->videoWidth() || !video->videoHeight()) {
 5841 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no video");
 5842 return false;
 5843 }
 5844 if (wouldTaintOrigin(video)) {
 5845 ec = SECURITY_ERR;
 5846 return false;
 5847 }
 5848 return true;
 5849}
 5850#endif
 5851
 5852void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
 5853{
 5854 if (isContextLostOrPending())
 5855 return;
 5856 if (index >= m_maxVertexAttribs) {
 5857 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
 5858 return;
 5859 }
 5860 // In GL, we skip setting vertexAttrib0 values.
 5861 if (index || isGLES2Compliant()) {
 5862 switch (expectedSize) {
 5863 case 1:
 5864 m_context->vertexAttrib1f(index, v0);
 5865 break;
 5866 case 2:
 5867 m_context->vertexAttrib2f(index, v0, v1);
 5868 break;
 5869 case 3:
 5870 m_context->vertexAttrib3f(index, v0, v1, v2);
 5871 break;
 5872 case 4:
 5873 m_context->vertexAttrib4f(index, v0, v1, v2, v3);
 5874 break;
 5875 }
 5876 }
 5877 VertexAttribValue& attribValue = m_vertexAttribValue[index];
 5878 attribValue.value[0] = v0;
 5879 attribValue.value[1] = v1;
 5880 attribValue.value[2] = v2;
 5881 attribValue.value[3] = v3;
 5882}
 5883
 5884void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
 5885{
 5886 if (isContextLostOrPending())
 5887 return;
 5888 if (!v) {
 5889 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5890 return;
 5891 }
 5892 vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize);
 5893}
 5894
 5895void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
 5896{
 5897 if (isContextLostOrPending())
 5898 return;
 5899 if (!v) {
 5900 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5901 return;
 5902 }
 5903 if (size < expectedSize) {
 5904 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
 5905 return;
 5906 }
 5907 if (index >= m_maxVertexAttribs) {
 5908 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
 5909 return;
 5910 }
 5911 // In GL, we skip setting vertexAttrib0 values.
 5912 if (index || isGLES2Compliant()) {
 5913 switch (expectedSize) {
 5914 case 1:
 5915 m_context->vertexAttrib1fv(index, v);
 5916 break;
 5917 case 2:
 5918 m_context->vertexAttrib2fv(index, v);
 5919 break;
 5920 case 3:
 5921 m_context->vertexAttrib3fv(index, v);
 5922 break;
 5923 case 4:
 5924 m_context->vertexAttrib4fv(index, v);
 5925 break;
 5926 }
 5927 }
 5928 VertexAttribValue& attribValue = m_vertexAttribValue[index];
 5929 attribValue.initValue();
 5930 for (int ii = 0; ii < expectedSize; ++ii)
 5931 attribValue.value[ii] = v[ii];
 5932}
 5933
 5934void WebGLRenderingContext::initVertexAttrib0()
 5935{
 5936 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
 5937
 5938 m_vertexAttrib0Buffer = createBuffer();
 5939 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
 5940 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
 5941 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
 5942 state.bufferBinding = m_vertexAttrib0Buffer;
 5943 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
 5944 m_context->enableVertexAttribArray(0);
 5945 m_vertexAttrib0BufferSize = 0;
 5946 m_vertexAttrib0BufferValue[0] = 0.0f;
 5947 m_vertexAttrib0BufferValue[1] = 0.0f;
 5948 m_vertexAttrib0BufferValue[2] = 0.0f;
 5949 m_vertexAttrib0BufferValue[3] = 1.0f;
 5950 m_forceAttrib0BufferRefill = false;
 5951 m_vertexAttrib0UsedBefore = false;
 5952}
 5953
 5954bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
 5955{
 5956 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
 5957 const VertexAttribValue& attribValue = m_vertexAttribValue[0];
 5958 if (!m_currentProgram)
 5959 return false;
 5960 bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
 5961 if (usingVertexAttrib0)
 5962 m_vertexAttrib0UsedBefore = true;
 5963 if (state.enabled && usingVertexAttrib0)
 5964 return false;
 5965 if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
 5966 return false;
 5967 m_vertexAttrib0UsedBefore = true;
 5968 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
 5969 GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
 5970 if (bufferDataSize > m_vertexAttrib0BufferSize) {
 5971 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
 5972 m_vertexAttrib0BufferSize = bufferDataSize;
 5973 m_forceAttrib0BufferRefill = true;
 5974 }
 5975 if (usingVertexAttrib0
 5976 && (m_forceAttrib0BufferRefill
 5977 || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
 5978 || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
 5979 || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
 5980 || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
 5981 auto bufferData = std::make_unique<GC3Dfloat[]>((numVertex + 1) * 4);
 5982 for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
 5983 bufferData[ii * 4] = attribValue.value[0];
 5984 bufferData[ii * 4 + 1] = attribValue.value[1];
 5985 bufferData[ii * 4 + 2] = attribValue.value[2];
 5986 bufferData[ii * 4 + 3] = attribValue.value[3];
 5987 }
 5988 m_vertexAttrib0BufferValue[0] = attribValue.value[0];
 5989 m_vertexAttrib0BufferValue[1] = attribValue.value[1];
 5990 m_vertexAttrib0BufferValue[2] = attribValue.value[2];
 5991 m_vertexAttrib0BufferValue[3] = attribValue.value[3];
 5992 m_forceAttrib0BufferRefill = false;
 5993 m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
 5994 }
 5995 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
 5996 return true;
 5997}
 5998
 5999void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
 6000{
 6001 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
 6002 if (state.bufferBinding != m_vertexAttrib0Buffer) {
 6003 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
 6004 m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
 6005 }
 6006 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
 6007}
 6008
 6009void WebGLRenderingContext::dispatchContextLostEvent()
 6010{
 6011 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
 6012 canvas()->dispatchEvent(event);
 6013 m_restoreAllowed = event->defaultPrevented();
 6014 if (m_contextLostMode == RealLostContext && m_restoreAllowed)
 6015 m_restoreTimer.startOneShot(0);
 6016}
 6017
 6018void WebGLRenderingContext::maybeRestoreContext()
 6019{
 6020 ASSERT(m_contextLost);
 6021 if (!m_contextLost)
 6022 return;
 6023
 6024 // The rendering context is not restored unless the default behavior of the
 6025 // webglcontextlost event was prevented earlier.
 6026 //
 6027 // Because of the way m_restoreTimer is set up for real vs. synthetic lost
 6028 // context events, we don't have to worry about this test short-circuiting
 6029 // the retry loop for real context lost events.
 6030 if (!m_restoreAllowed)
 6031 return;
 6032
 6033 int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
 6034
 6035 switch (contextLostReason) {
 6036 case GraphicsContext3D::NO_ERROR:
 6037 // The GraphicsContext3D implementation might not fully
 6038 // support GL_ARB_robustness semantics yet. Alternatively, the
 6039 // WEBGL_lose_context extension might have been used to force
 6040 // a lost context.
 6041 break;
 6042 case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
 6043 // The rendering context is not restored if this context was
 6044 // guilty of causing the graphics reset.
 6045 printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
 6046 return;
 6047 case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
 6048 // Always allow the context to be restored.
 6049 break;
 6050 case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
 6051 // Warn. Ideally, prompt the user telling them that WebGL
 6052 // content on the page might have caused the graphics card to
 6053 // reset and ask them whether they want to continue running
 6054 // the content. Only if they say "yes" should we start
 6055 // attempting to restore the context.
 6056 printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
 6057 break;
 6058 }
 6059
 6060 Frame* frame = canvas()->document().frame();
 6061 if (!frame)
 6062 return;
 6063
 6064 if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled()))
 6065 return;
 6066
 6067 FrameView* view = frame->view();
 6068 if (!view)
 6069 return;
 6070 ScrollView* root = view->root();
 6071 if (!root)
 6072 return;
 6073 HostWindow* hostWindow = root->hostWindow();
 6074 if (!hostWindow)
 6075 return;
 6076
 6077 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, hostWindow));
 6078 if (!context) {
 6079 if (m_contextLostMode == RealLostContext)
 6080 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
 6081 else
 6082 // This likely shouldn't happen but is the best way to report it to the WebGL app.
 6083 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context");
 6084 return;
 6085 }
 6086
 6087 // Construct a new drawing buffer with the new GraphicsContext3D.
 6088 if (m_drawingBuffer) {
 6089 m_drawingBuffer->discardResources();
 6090 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
 6091 DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
 6092 m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha);
 6093 m_drawingBuffer->bind();
 6094 }
 6095
 6096 m_context = context;
 6097 m_contextLost = false;
 6098 setupFlags();
 6099 initializeNewContext();
 6100 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
 6101}
 6102
 6103String WebGLRenderingContext::ensureNotNull(const String& text) const
 6104{
 6105 if (text.isNull())
 6106 return WTF::emptyString();
 6107 return text;
 6108}
 6109
 6110WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
 6111 : m_buffers(std::make_unique<std::unique_ptr<ImageBuffer>[]>(capacity))
 6112 , m_capacity(capacity)
 6113{
 6114}
 6115
 6116ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
 6117{
 6118 int i;
 6119 for (i = 0; i < m_capacity; ++i) {
 6120 ImageBuffer* buf = m_buffers[i].get();
 6121 if (!buf)
 6122 break;
 6123 if (buf->logicalSize() != size)
 6124 continue;
 6125 bubbleToFront(i);
 6126 return buf;
 6127 }
 6128
 6129 std::unique_ptr<ImageBuffer> temp = ImageBuffer::create(size, 1);
 6130 if (!temp)
 6131 return nullptr;
 6132 i = std::min(m_capacity - 1, i);
 6133 m_buffers[i] = WTF::move(temp);
 6134
 6135 ImageBuffer* buf = m_buffers[i].get();
 6136 bubbleToFront(i);
 6137 return buf;
 6138}
 6139
 6140void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
 6141{
 6142 for (int i = idx; i > 0; --i)
 6143 m_buffers[i].swap(m_buffers[i-1]);
 6144}
 6145
 6146namespace {
 6147
 6148 String GetErrorString(GC3Denum error)
 6149 {
 6150 switch (error) {
 6151 case GraphicsContext3D::INVALID_ENUM:
 6152 return "INVALID_ENUM";
 6153 case GraphicsContext3D::INVALID_VALUE:
 6154 return "INVALID_VALUE";
 6155 case GraphicsContext3D::INVALID_OPERATION:
 6156 return "INVALID_OPERATION";
 6157 case GraphicsContext3D::OUT_OF_MEMORY:
 6158 return "OUT_OF_MEMORY";
 6159 case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
 6160 return "INVALID_FRAMEBUFFER_OPERATION";
 6161 case GraphicsContext3D::CONTEXT_LOST_WEBGL:
 6162 return "CONTEXT_LOST_WEBGL";
 6163 default:
 6164 return String::format("WebGL ERROR(%04x)", error);
 6165 }
 6166 }
 6167
 6168} // namespace anonymous
 6169
 6170void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display)
 6171{
 6172 if (m_synthesizedErrorsToConsole && display == DisplayInConsole) {
 6173 String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description);
 6174 printGLErrorToConsole(str);
 6175 }
 6176 m_context->synthesizeGLError(error);
 6177}
 6178
 6179
 6180void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description)
 6181{
 6182 if (m_synthesizedErrorsToConsole) {
 6183 String str = String("WebGL: ") + String(functionName) + ": " + String(description);
 6184 printGLErrorToConsole(str);
 6185 }
 6186}
 6187
 6188void WebGLRenderingContext::applyStencilTest()
 6189{
 6190 bool haveStencilBuffer = false;
 6191
 6192 if (m_framebufferBinding)
 6193 haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
 6194 else {
 6195 RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
 6196 haveStencilBuffer = attributes->stencil();
 6197 }
 6198 enableOrDisable(GraphicsContext3D::STENCIL_TEST,
 6199 m_stencilEnabled && haveStencilBuffer);
 6200}
 6201
 6202void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable)
 6203{
 6204 if (enable)
 6205 m_context->enable(capability);
 6206 else
 6207 m_context->disable(capability);
 6208}
 6209
 6210IntSize WebGLRenderingContext::clampedCanvasSize()
 6211{
 6212 return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
 6213 clamp(canvas()->height(), 1, m_maxViewportDims[1]));
 6214}
 6215
 6216GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
 6217{
 6218 if (!supportsDrawBuffers())
 6219 return 0;
 6220 if (!m_maxDrawBuffers)
 6221 m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
 6222 if (!m_maxColorAttachments)
 6223 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
 6224 // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
 6225 return std::min(m_maxDrawBuffers, m_maxColorAttachments);
 6226}
 6227
 6228GC3Dint WebGLRenderingContext::getMaxColorAttachments()
 6229{
 6230 if (!supportsDrawBuffers())
 6231 return 0;
 6232 if (!m_maxColorAttachments)
 6233 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
 6234 return m_maxColorAttachments;
 6235}
 6236
 6237void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf)
 6238{
 6239 m_backDrawBuffer = buf;
 6240}
 6241
 6242void WebGLRenderingContext::restoreCurrentFramebuffer()
 6243{
 6244 ExceptionCode ec;
 6245 bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get(), ec);
 6246}
 6247
 6248void WebGLRenderingContext::restoreCurrentTexture2D()
 6249{
 6250 ExceptionCode ec;
 6251 bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUnit].texture2DBinding.get(), ec);
 6252}
 6253
 6254bool WebGLRenderingContext::supportsDrawBuffers()
 6255{
 6256 if (!m_drawBuffersWebGLRequirementsChecked) {
 6257 m_drawBuffersWebGLRequirementsChecked = true;
 6258 m_drawBuffersSupported = WebGLDrawBuffers::supported(this);
 6259 }
 6260 return m_drawBuffersSupported;
 6261}
 6262
 6263void WebGLRenderingContext::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
 6264{
 6265 if (!primcount) {
 6266 markContextChanged();
 6267 return;
 6268 }
 6269
 6270 if (!validateDrawArrays("drawArraysInstanced", mode, first, count, primcount))
 6271 return;
 6272
 6273 clearIfComposited();
 6274
 6275 bool vertexAttrib0Simulated = false;
 6276 if (!isGLES2Compliant())
 6277 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
 6278 if (!isGLES2NPOTStrict())
 6279 checkTextureCompleteness("drawArraysInstanced", true);
 6280
 6281 m_context->drawArraysInstanced(mode, first, count, primcount);
 6282
 6283 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 6284 restoreStatesAfterVertexAttrib0Simulation();
 6285 if (!isGLES2NPOTStrict())
 6286 checkTextureCompleteness("drawArraysInstanced", false);
 6287 markContextChanged();
 6288}
 6289
 6290void WebGLRenderingContext::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount)
 6291{
 6292 if (!primcount) {
 6293 markContextChanged();
 6294 return;
 6295 }
 6296
 6297 unsigned numElements = 0;
 6298 if (!validateDrawElements("drawElementsInstanced", mode, count, type, offset, numElements, primcount))
 6299 return;
 6300
 6301 clearIfComposited();
 6302
 6303 bool vertexAttrib0Simulated = false;
 6304 if (!isGLES2Compliant()) {
 6305 if (!numElements)
 6306 validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
 6307 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
 6308 }
 6309 if (!isGLES2NPOTStrict())
 6310 checkTextureCompleteness("drawElementsInstanced", true);
 6311
 6312 m_context->drawElementsInstanced(mode, count, type, static_cast<GC3Dintptr>(offset), primcount);
 6313
 6314 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 6315 restoreStatesAfterVertexAttrib0Simulation();
 6316 if (!isGLES2NPOTStrict())
 6317 checkTextureCompleteness("drawElementsInstanced", false);
 6318 markContextChanged();
 6319}
 6320
 6321void WebGLRenderingContext::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
 6322{
 6323 if (isContextLostOrPending())
 6324 return;
 6325
 6326 if (index >= m_maxVertexAttribs) {
 6327 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor", "index out of range");
 6328 return;
 6329 }
 6330
 6331 m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor);
 6332 m_context->vertexAttribDivisor(index, divisor);
 6333}
 6334
 6335
 6336} // namespace WebCore
 6337
 6338#endif // ENABLE(WEBGL)
176994

Source/WebCore/html/canvas/WebGL1RenderingContext.cpp

11/*
2  * Copyright (C) 2009, 2013, 2014 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2626#include "config.h"
2727
2828#if ENABLE(WEBGL)
29 
30 #include "WebGLRenderingContext.h"
31 
32 #include "ANGLEInstancedArrays.h"
33 #include "CachedImage.h"
34 #include "DOMWindow.h"
35 #include "Document.h"
36 #include "EXTShaderTextureLOD.h"
37 #include "EXTTextureFilterAnisotropic.h"
38 #include "ExceptionCode.h"
39 #include "Extensions3D.h"
40 #include "Frame.h"
41 #include "FrameLoader.h"
42 #include "FrameLoaderClient.h"
43 #include "FrameView.h"
44 #include "GraphicsContext.h"
45 #include "HTMLCanvasElement.h"
46 #include "HTMLImageElement.h"
47 #include "HTMLVideoElement.h"
48 #include "ImageBuffer.h"
49 #include "ImageData.h"
50 #include "IntSize.h"
51 #include "Logging.h"
52 #include "MainFrame.h"
53 #include "NotImplemented.h"
54 #include "OESElementIndexUint.h"
55 #include "OESStandardDerivatives.h"
56 #include "OESTextureFloat.h"
57 #include "OESTextureFloatLinear.h"
58 #include "OESTextureHalfFloat.h"
59 #include "OESTextureHalfFloatLinear.h"
60 #include "OESVertexArrayObject.h"
61 #include "Page.h"
62 #include "RenderBox.h"
63 #include "Settings.h"
64 #include "WebGLActiveInfo.h"
65 #include "WebGLBuffer.h"
66 #include "WebGLCompressedTextureATC.h"
67 #include "WebGLCompressedTexturePVRTC.h"
68 #include "WebGLCompressedTextureS3TC.h"
69 #include "WebGLContextAttributes.h"
70 #include "WebGLContextEvent.h"
71 #include "WebGLContextGroup.h"
72 #include "WebGLDebugRendererInfo.h"
73 #include "WebGLDebugShaders.h"
74 #include "WebGLDepthTexture.h"
75 #include "WebGLDrawBuffers.h"
76 #include "WebGLFramebuffer.h"
77 #include "WebGLLoseContext.h"
78 #include "WebGLProgram.h"
79 #include "WebGLRenderbuffer.h"
80 #include "WebGLShader.h"
81 #include "WebGLShaderPrecisionFormat.h"
82 #include "WebGLTexture.h"
83 #include "WebGLUniformLocation.h"
84 
85 #include <runtime/JSCInlines.h>
86 #include <runtime/TypedArrayInlines.h>
87 #include <runtime/Uint32Array.h>
88 #include <wtf/StdLibExtras.h>
89 #include <wtf/text/CString.h>
90 #include <wtf/text/StringBuilder.h>
 29#include "WebGL1RenderingContext.h"
9130
9231namespace WebCore {
9332
94 const double secondsBetweenRestoreAttempts = 1.0;
95 const int maxGLErrorsAllowedToConsole = 256;
96 
97 namespace {
98 
99  class ScopedDrawingBufferBinder {
100  public:
101  ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
102  : m_drawingBuffer(drawingBuffer)
103  , m_framebufferBinding(framebufferBinding)
104  {
105  // Commit DrawingBuffer if needed (e.g., for multisampling)
106  if (!m_framebufferBinding && m_drawingBuffer)
107  m_drawingBuffer->commit();
108  }
109 
110  ~ScopedDrawingBufferBinder()
111  {
112  // Restore DrawingBuffer if needed
113  if (!m_framebufferBinding && m_drawingBuffer)
114  m_drawingBuffer->bind();
115  }
116 
117  private:
118  DrawingBuffer* m_drawingBuffer;
119  WebGLFramebuffer* m_framebufferBinding;
120  };
121 
122  Platform3DObject objectOrZero(WebGLObject* object)
123  {
124  return object ? object->object() : 0;
125  }
126 
127  void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
128  {
129  ASSERT(clippedStart && clippedRange);
130  if (start < 0) {
131  range += start;
132  start = 0;
133  }
134  GC3Dint end = start + range;
135  if (end > sourceRange)
136  range -= end - sourceRange;
137  *clippedStart = start;
138  *clippedRange = range;
139  }
140 
141  // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
142  bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
143  GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
144  GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
145  {
146  ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
147  clip1D(x, width, sourceWidth, clippedX, clippedWidth);
148  clip1D(y, height, sourceHeight, clippedY, clippedHeight);
149  return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
150  }
151 
152  GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
153  {
154  if (value < min)
155  value = min;
156  if (value > max)
157  value = max;
158  return value;
159  }
160 
161  // Return true if a character belongs to the ASCII subset as defined in
162  // GLSL ES 1.0 spec section 3.1.
163  bool validateCharacter(unsigned char c)
164  {
165  // Printing characters are valid except " $ ` @ \ ' DEL.
166  if (c >= 32 && c <= 126
167  && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
168  return true;
169  // Horizontal tab, line feed, vertical tab, form feed, carriage return
170  // are also valid.
171  if (c >= 9 && c <= 13)
172  return true;
173  return false;
174  }
175 
176  bool isPrefixReserved(const String& name)
177  {
178  if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_"))
179  return true;
180  return false;
181  }
182 
183  // Strips comments from shader text. This allows non-ASCII characters
184  // to be used in comments without potentially breaking OpenGL
185  // implementations not expecting characters outside the GLSL ES set.
186  class StripComments {
187  public:
188  StripComments(const String& str)
189  : m_parseState(BeginningOfLine)
190  , m_sourceString(str)
191  , m_length(str.length())
192  , m_position(0)
193  {
194  parse();
195  }
196 
197  String result()
198  {
199  return m_builder.toString();
200  }
201 
202  private:
203  bool hasMoreCharacters() const
204  {
205  return (m_position < m_length);
206  }
207 
208  void parse()
209  {
210  while (hasMoreCharacters()) {
211  process(current());
212  // process() might advance the position.
213  if (hasMoreCharacters())
214  advance();
215  }
216  }
217 
218  void process(UChar);
219 
220  bool peek(UChar& character) const
221  {
222  if (m_position + 1 >= m_length)
223  return false;
224  character = m_sourceString[m_position + 1];
225  return true;
226  }
227 
228  UChar current() const
229  {
230  ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length);
231  return m_sourceString[m_position];
232  }
233 
234  void advance()
235  {
236  ++m_position;
237  }
238 
239  bool isNewline(UChar character) const
240  {
241  // Don't attempt to canonicalize newline related characters.
242  return (character == '\n' || character == '\r');
243  }
244 
245  void emit(UChar character)
246  {
247  m_builder.append(character);
248  }
249 
250  enum ParseState {
251  // Have not seen an ASCII non-whitespace character yet on
252  // this line. Possible that we might see a preprocessor
253  // directive.
254  BeginningOfLine,
255 
256  // Have seen at least one ASCII non-whitespace character
257  // on this line.
258  MiddleOfLine,
259 
260  // Handling a preprocessor directive. Passes through all
261  // characters up to the end of the line. Disables comment
262  // processing.
263  InPreprocessorDirective,
264 
265  // Handling a single-line comment. The comment text is
266  // replaced with a single space.
267  InSingleLineComment,
268 
269  // Handling a multi-line comment. Newlines are passed
270  // through to preserve line numbers.
271  InMultiLineComment
272  };
273 
274  ParseState m_parseState;
275  String m_sourceString;
276  unsigned m_length;
277  unsigned m_position;
278  StringBuilder m_builder;
279  };
280 
281  void StripComments::process(UChar c)
282  {
283  if (isNewline(c)) {
284  // No matter what state we are in, pass through newlines
285  // so we preserve line numbers.
286  emit(c);
287 
288  if (m_parseState != InMultiLineComment)
289  m_parseState = BeginningOfLine;
290 
291  return;
292  }
293 
294  UChar temp = 0;
295  switch (m_parseState) {
296  case BeginningOfLine:
297  if (WTF::isASCIISpace(c)) {
298  emit(c);
299  break;
300  }
301 
302  if (c == '#') {
303  m_parseState = InPreprocessorDirective;
304  emit(c);
305  break;
306  }
307 
308  // Transition to normal state and re-handle character.
309  m_parseState = MiddleOfLine;
310  process(c);
311  break;
312 
313  case MiddleOfLine:
314  if (c == '/' && peek(temp)) {
315  if (temp == '/') {
316  m_parseState = InSingleLineComment;
317  emit(' ');
318  advance();
319  break;
320  }
321 
322  if (temp == '*') {
323  m_parseState = InMultiLineComment;
324  // Emit the comment start in case the user has
325  // an unclosed comment and we want to later
326  // signal an error.
327  emit('/');
328  emit('*');
329  advance();
330  break;
331  }
332  }
333 
334  emit(c);
335  break;
336 
337  case InPreprocessorDirective:
338  // No matter what the character is, just pass it
339  // through. Do not parse comments in this state. This
340  // might not be the right thing to do long term, but it
341  // should handle the #error preprocessor directive.
342  emit(c);
343  break;
344 
345  case InSingleLineComment:
346  // The newline code at the top of this function takes care
347  // of resetting our state when we get out of the
348  // single-line comment. Swallow all other characters.
349  break;
350 
351  case InMultiLineComment:
352  if (c == '*' && peek(temp) && temp == '/') {
353  emit('*');
354  emit('/');
355  m_parseState = MiddleOfLine;
356  advance();
357  break;
358  }
359 
360  // Swallow all other characters. Unclear whether we may
361  // want or need to just emit a space per character to try
362  // to preserve column numbers for debugging purposes.
363  break;
364  }
365  }
366 } // namespace anonymous
367 
368 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
369  WTF_MAKE_FAST_ALLOCATED;
370 public:
371  explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { }
372  virtual void onContextLost() override { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); }
373  virtual ~WebGLRenderingContextLostCallback() {}
374 private:
375  WebGLRenderingContext* m_context;
376 };
377 
378 class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback {
379  WTF_MAKE_FAST_ALLOCATED;
380 public:
381  explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb) : m_context(cb) { }
382  virtual void onErrorMessage(const String& message, GC3Dint) override
383  {
384  if (m_context->m_synthesizedErrorsToConsole)
385  m_context->printGLErrorToConsole(message);
386  }
387  virtual ~WebGLRenderingContextErrorMessageCallback() { }
388 private:
389  WebGLRenderingContext* m_context;
390 };
391 
392 std::unique_ptr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
393 {
394  Document& document = canvas->document();
395  Frame* frame = document.frame();
396  if (!frame)
397  return nullptr;
398 
399  // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in
400  // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension.
401  if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) {
402  canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context."));
403  return nullptr;
404  }
405 
406  bool isPendingPolicyResolution = false;
407  Document& topDocument = document.topDocument();
408  Page* page = topDocument.page();
409  if (page && !topDocument.url().isLocalFile()) {
410  WebGLLoadPolicy policy = page->mainFrame().loader().client().webGLPolicyForURL(topDocument.url());
411 
412  if (policy == WebGLBlockCreation) {
413  LOG(WebGL, "The policy for this URL (%s) is to block WebGL.", topDocument.url().host().utf8().data());
414  return nullptr;
415  }
416 
417  if (policy == WebGLPendingCreation) {
418  LOG(WebGL, "WebGL policy is pending. May need to be resolved later.");
419  isPendingPolicyResolution = true;
420  }
421  }
422 
423  GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
424 
425  if (attributes.antialias) {
426  if (!frame->settings().openGLMultisamplingEnabled())
427  attributes.antialias = false;
428  }
429 
430  attributes.noExtensions = true;
431  attributes.shareResources = false;
432  attributes.preferDiscreteGPU = true;
433 
434  if (frame->settings().forceSoftwareWebGLRendering())
435  attributes.forceSoftwareRenderer = true;
436 
437  if (page)
438  attributes.devicePixelRatio = page->deviceScaleFactor();
439 
440  if (isPendingPolicyResolution) {
441  LOG(WebGL, "Create a WebGL context that looks real, but will require a policy resolution if used.");
442  std::unique_ptr<WebGLRenderingContext> renderingContext(new WebGLRenderingContext(canvas, attributes));
443  renderingContext->suspendIfNeeded();
444  return renderingContext;
445  }
446 
447  HostWindow* hostWindow = document.view()->root()->hostWindow();
448  RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
449 
450  if (!context || !context->makeContextCurrent()) {
451  canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
452  return nullptr;
453  }
454 
455  Extensions3D* extensions = context->getExtensions();
456  if (extensions->supports("GL_EXT_debug_marker"))
457  extensions->pushGroupMarkerEXT("WebGLRenderingContext");
458 
459  std::unique_ptr<WebGLRenderingContext> renderingContext(new WebGLRenderingContext(canvas, context, attributes));
460  renderingContext->suspendIfNeeded();
461 
462  return renderingContext;
463 }
464 
465 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
466  : CanvasRenderingContext(passedCanvas)
467  , ActiveDOMObject(&passedCanvas->document())
468  , m_context(0)
469  , m_drawingBuffer(0)
470  , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContext::dispatchContextLostEvent)
471  , m_restoreAllowed(false)
472  , m_restoreTimer(*this, &WebGLRenderingContext::maybeRestoreContext)
473  , m_generatedImageCache(0)
474  , m_contextLost(false)
475  , m_contextLostMode(SyntheticLostContext)
476  , m_attributes(attributes)
477  , m_synthesizedErrorsToConsole(true)
478  , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
479  , m_isPendingPolicyResolution(true)
480  , m_hasRequestedPolicyResolution(false)
481 {
482 }
483 
484 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
485  GraphicsContext3D::Attributes attributes)
486  : CanvasRenderingContext(passedCanvas)
487  , ActiveDOMObject(&passedCanvas->document())
488  , m_context(context)
489  , m_drawingBuffer(0)
490  , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContext::dispatchContextLostEvent)
491  , m_restoreAllowed(false)
492  , m_restoreTimer(*this, &WebGLRenderingContext::maybeRestoreContext)
493  , m_generatedImageCache(4)
494  , m_contextLost(false)
495  , m_contextLostMode(SyntheticLostContext)
496  , m_attributes(attributes)
497  , m_synthesizedErrorsToConsole(true)
498  , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
499  , m_isPendingPolicyResolution(false)
500  , m_hasRequestedPolicyResolution(false)
501 {
502  ASSERT(m_context);
503  m_contextGroup = WebGLContextGroup::create();
504  m_contextGroup->addContext(this);
505 
506  m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
507  m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
508 
509  if (m_drawingBuffer)
510  m_drawingBuffer->bind();
511 
512  setupFlags();
513  initializeNewContext();
514 }
515 
516 void WebGLRenderingContext::initializeNewContext()
517 {
518  ASSERT(!m_contextLost);
519  m_needsUpdate = true;
520  m_markedCanvasDirty = false;
521  m_activeTextureUnit = 0;
522  m_packAlignment = 4;
523  m_unpackAlignment = 4;
524  m_unpackFlipY = false;
525  m_unpackPremultiplyAlpha = false;
526  m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
527  m_boundArrayBuffer = 0;
528  m_currentProgram = 0;
529  m_framebufferBinding = 0;
530  m_renderbufferBinding = 0;
531  m_depthMask = true;
532  m_stencilEnabled = false;
533  m_stencilMask = 0xFFFFFFFF;
534  m_stencilMaskBack = 0xFFFFFFFF;
535  m_stencilFuncRef = 0;
536  m_stencilFuncRefBack = 0;
537  m_stencilFuncMask = 0xFFFFFFFF;
538  m_stencilFuncMaskBack = 0xFFFFFFFF;
539  m_layerCleared = false;
540  m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
541 
542  m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
543  m_scissorEnabled = false;
544  m_clearDepth = 1;
545  m_clearStencil = 0;
546  m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
547 
548  GC3Dint numCombinedTextureImageUnits = 0;
549  m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
550  m_textureUnits.clear();
551  m_textureUnits.resize(numCombinedTextureImageUnits);
552 
553  GC3Dint numVertexAttribs = 0;
554  m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
555  m_maxVertexAttribs = numVertexAttribs;
556 
557  m_maxTextureSize = 0;
558  m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
559  m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
560  m_maxCubeMapTextureSize = 0;
561  m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
562  m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
563  m_maxRenderbufferSize = 0;
564  m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
565 
566  // These two values from EXT_draw_buffers are lazily queried.
567  m_maxDrawBuffers = 0;
568  m_maxColorAttachments = 0;
569 
570  m_backDrawBuffer = GraphicsContext3D::BACK;
571  m_drawBuffersWebGLRequirementsChecked = false;
572  m_drawBuffersSupported = false;
573 
574  m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
575  addContextObject(m_defaultVertexArrayObject.get());
576  m_boundVertexArrayObject = m_defaultVertexArrayObject;
577 
578  m_vertexAttribValue.resize(m_maxVertexAttribs);
579 
580  if (!isGLES2NPOTStrict())
581  createFallbackBlackTextures1x1();
582  if (!isGLES2Compliant())
583  initVertexAttrib0();
584 
585  IntSize canvasSize = clampedCanvasSize();
586  if (m_drawingBuffer)
587  m_drawingBuffer->reset(canvasSize);
588 
589  m_context->reshape(canvasSize.width(), canvasSize.height());
590  m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
591  m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
592 
593  m_context->setContextLostCallback(std::make_unique<WebGLRenderingContextLostCallback>(this));
594  m_context->setErrorMessageCallback(std::make_unique<WebGLRenderingContextErrorMessageCallback>(this));
595 }
596 
597 void WebGLRenderingContext::setupFlags()
598 {
599  ASSERT(m_context);
600 
601  if (Page* page = canvas()->document().page())
602  m_synthesizedErrorsToConsole = page->settings().webGLErrorsToConsoleEnabled();
603 
604  m_isGLES2Compliant = m_context->isGLES2Compliant();
605  m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
606  m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
607  if (m_isGLES2Compliant) {
608  m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
609  m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
610  } else {
611  m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
612  m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
613  }
614  m_isRobustnessEXTSupported = m_context->getExtensions()->isEnabled("GL_EXT_robustness");
615 }
616 
617 bool WebGLRenderingContext::allowPrivilegedExtensions() const
618 {
619  if (Page* page = canvas()->document().page())
620  return page->settings().privilegedWebGLExtensionsEnabled();
621  return false;
622 }
623 
624 void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format)
625 {
626  if (!m_compressedTextureFormats.contains(format))
627  m_compressedTextureFormats.append(format);
628 }
629 
630 WebGLRenderingContext::~WebGLRenderingContext()
631 {
632  // Remove all references to WebGLObjects so if they are the last reference
633  // they will be freed before the last context is removed from the context group.
634  m_boundArrayBuffer = nullptr;
635  m_defaultVertexArrayObject = nullptr;
636  m_boundVertexArrayObject = nullptr;
637  m_vertexAttrib0Buffer = nullptr;
638  m_currentProgram = nullptr;
639  m_framebufferBinding = nullptr;
640  m_renderbufferBinding = nullptr;
641 
642  for (size_t i = 0; i < m_textureUnits.size(); ++i) {
643  m_textureUnits[i].texture2DBinding = nullptr;
644  m_textureUnits[i].textureCubeMapBinding = nullptr;
645  }
646 
647  m_blackTexture2D = nullptr;
648  m_blackTextureCubeMap = nullptr;
649 
650  if (!m_isPendingPolicyResolution) {
651  detachAndRemoveAllObjects();
652  destroyGraphicsContext3D();
653  m_contextGroup->removeContext(this);
654  }
655 }
656 
657 void WebGLRenderingContext::destroyGraphicsContext3D()
658 {
659  if (m_isPendingPolicyResolution)
660  return;
661 
662  // The drawing buffer holds a context reference. It must also be destroyed
663  // in order for the context to be released.
664  if (m_drawingBuffer)
665  m_drawingBuffer.clear();
666 
667  if (m_context) {
668  m_context->setContextLostCallback(nullptr);
669  m_context->setErrorMessageCallback(nullptr);
670  m_context.clear();
671  }
672 }
673 
674 void WebGLRenderingContext::markContextChanged()
675 {
676  if (m_framebufferBinding)
677  return;
678 
679  m_context->markContextChanged();
680 
681  if (m_drawingBuffer)
682  m_drawingBuffer->markContentsChanged();
683 
684  m_layerCleared = false;
685  RenderBox* renderBox = canvas()->renderBox();
686  if (isAccelerated() && renderBox && renderBox->hasAcceleratedCompositing()) {
687  m_markedCanvasDirty = true;
688  canvas()->clearCopiedImage();
689  renderBox->contentChanged(CanvasChanged);
690  } else {
691  if (!m_markedCanvasDirty) {
692  m_markedCanvasDirty = true;
693  canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
694  }
695  }
696 }
697 
698 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
699 {
700  if (isContextLostOrPending())
701  return false;
702 
703  if (!m_context->layerComposited() || m_layerCleared
704  || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
705  return false;
706 
707  RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
708 
709  // Determine if it's possible to combine the clear the user asked for and this clear.
710  bool combinedClear = mask && !m_scissorEnabled;
711 
712  m_context->disable(GraphicsContext3D::SCISSOR_TEST);
713  if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
714  m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
715  m_colorMask[1] ? m_clearColor[1] : 0,
716  m_colorMask[2] ? m_clearColor[2] : 0,
717  m_colorMask[3] ? m_clearColor[3] : 0);
718  else
719  m_context->clearColor(0, 0, 0, 0);
720  m_context->colorMask(true, true, true, true);
721  GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
722  if (contextAttributes->depth()) {
723  if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
724  m_context->clearDepth(1.0f);
725  clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
726  m_context->depthMask(true);
727  }
728  if (contextAttributes->stencil()) {
729  if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
730  m_context->clearStencil(m_clearStencil & m_stencilMask);
731  else
732  m_context->clearStencil(0);
733  clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
734  m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
735  }
736  if (m_drawingBuffer)
737  m_drawingBuffer->clearFramebuffers(clearMask);
738  else {
739  if (m_framebufferBinding)
740  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
741  m_context->clear(clearMask);
742  }
743 
744  restoreStateAfterClear();
745  if (m_framebufferBinding)
746  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
747  m_layerCleared = true;
748 
749  return combinedClear;
750 }
751 
752 void WebGLRenderingContext::restoreStateAfterClear()
753 {
754  // Restore the state that the context set.
755  if (m_scissorEnabled)
756  m_context->enable(GraphicsContext3D::SCISSOR_TEST);
757  m_context->clearColor(m_clearColor[0], m_clearColor[1],
758  m_clearColor[2], m_clearColor[3]);
759  m_context->colorMask(m_colorMask[0], m_colorMask[1],
760  m_colorMask[2], m_colorMask[3]);
761  m_context->clearDepth(m_clearDepth);
762  m_context->clearStencil(m_clearStencil);
763  m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
764  m_context->depthMask(m_depthMask);
765 }
766 
767 void WebGLRenderingContext::markLayerComposited()
768 {
769  if (isContextLostOrPending())
770  return;
771  m_context->markLayerComposited();
772 }
773 
774 void WebGLRenderingContext::paintRenderingResultsToCanvas()
775 {
776  if (isContextLostOrPending())
777  return;
778 
779  if (canvas()->document().printing())
780  canvas()->clearPresentationCopy();
781 
782  // Until the canvas is written to by the application, the clear that
783  // happened after it was composited should be ignored by the compositor.
784  if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
785  m_context->paintCompositedResultsToCanvas(canvas()->buffer());
786 
787  canvas()->makePresentationCopy();
788  } else
789  canvas()->clearPresentationCopy();
790  clearIfComposited();
791 
792  if (!m_markedCanvasDirty && !m_layerCleared)
793  return;
794 
795  canvas()->clearCopiedImage();
796  m_markedCanvasDirty = false;
797 
798  if (m_drawingBuffer)
799  m_drawingBuffer->commit();
800  m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get());
801 
802  if (m_drawingBuffer) {
803  if (m_framebufferBinding)
804  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
805  else
806  m_drawingBuffer->bind();
807  }
808 }
809 
810 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
811 {
812  if (isContextLostOrPending())
813  return nullptr;
814  clearIfComposited();
815  if (m_drawingBuffer)
816  m_drawingBuffer->commit();
817  RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
818 
819  if (m_drawingBuffer) {
820  if (m_framebufferBinding)
821  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
822  else
823  m_drawingBuffer->bind();
824  }
825 
826  return imageData;
827 }
828 
829 void WebGLRenderingContext::reshape(int width, int height)
830 {
831  if (isContextLostOrPending())
832  return;
833 
834  // This is an approximation because at WebGLRenderingContext level we don't
835  // know if the underlying FBO uses textures or renderbuffers.
836  GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
837  // Limit drawing buffer size to 4k to avoid memory exhaustion.
838  const int sizeUpperLimit = 4096;
839  maxSize = std::min(maxSize, sizeUpperLimit);
840  GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
841  GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
842  width = clamp(width, 1, maxWidth);
843  height = clamp(height, 1, maxHeight);
844 
845  if (m_needsUpdate) {
846  RenderBox* renderBox = canvas()->renderBox();
847  if (renderBox && renderBox->hasAcceleratedCompositing())
848  renderBox->contentChanged(CanvasChanged);
849  m_needsUpdate = false;
850  }
851 
852  // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
853  // clear (and this matches what reshape will do).
854  if (m_drawingBuffer) {
855  m_drawingBuffer->reset(IntSize(width, height));
856  restoreStateAfterClear();
857  } else
858  m_context->reshape(width, height);
859 
860  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].texture2DBinding.get()));
861  m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get()));
862  if (m_framebufferBinding)
863  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
864 }
865 
866 int WebGLRenderingContext::drawingBufferWidth() const
867 {
868  if (m_drawingBuffer)
869  return m_drawingBuffer->size().width();
870 
871  return m_context->getInternalFramebufferSize().width();
872 }
873 
874 int WebGLRenderingContext::drawingBufferHeight() const
875 {
876  if (m_drawingBuffer)
877  return m_drawingBuffer->size().height();
878 
879  return m_context->getInternalFramebufferSize().height();
880 }
881 
882 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
883 {
884  switch (type) {
885  case GraphicsContext3D::BYTE:
886  return sizeof(GC3Dbyte);
887  case GraphicsContext3D::UNSIGNED_BYTE:
888  return sizeof(GC3Dubyte);
889  case GraphicsContext3D::SHORT:
890  return sizeof(GC3Dshort);
891  case GraphicsContext3D::UNSIGNED_SHORT:
892  return sizeof(GC3Dushort);
893  case GraphicsContext3D::INT:
894  return sizeof(GC3Dint);
895  case GraphicsContext3D::UNSIGNED_INT:
896  return sizeof(GC3Duint);
897  case GraphicsContext3D::FLOAT:
898  return sizeof(GC3Dfloat);
899  }
900  ASSERT_NOT_REACHED();
901  return 0;
902 }
903 
904 void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
905 {
906  UNUSED_PARAM(ec);
907  if (isContextLostOrPending())
908  return;
909  if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
910  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range");
911  return;
912  }
913  m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
914  m_context->activeTexture(texture);
915 
916  if (m_drawingBuffer)
917  m_drawingBuffer->setActiveTextureUnit(texture);
918 }
919 
920 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
921 {
922  UNUSED_PARAM(ec);
923  if (isContextLostOrPending() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader))
924  return;
925  if (!program->attachShader(shader)) {
926  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
927  return;
928  }
929  m_context->attachShader(objectOrZero(program), objectOrZero(shader));
930  shader->onAttached();
931 }
932 
933 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
934 {
935  UNUSED_PARAM(ec);
936  if (isContextLostOrPending() || !validateWebGLObject("bindAttribLocation", program))
937  return;
938  if (!validateLocationLength("bindAttribLocation", name))
939  return;
940  if (!validateString("bindAttribLocation", name))
941  return;
942  if (isPrefixReserved(name)) {
943  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix");
944  return;
945  }
946  if (index >= m_maxVertexAttribs) {
947  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range");
948  return;
949  }
950  m_context->bindAttribLocation(objectOrZero(program), index, name);
951 }
952 
953 bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted)
954 {
955  deleted = false;
956  if (isContextLostOrPending())
957  return false;
958  if (object) {
959  if (!object->validate(contextGroup(), this)) {
960  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context");
961  return false;
962  }
963  deleted = !object->object();
964  }
965  return true;
966 }
967 
968 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
969 {
970  UNUSED_PARAM(ec);
971  bool deleted;
972  if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
973  return;
974  if (deleted)
975  buffer = 0;
976  if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
977  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets");
978  return;
979  }
980  if (target == GraphicsContext3D::ARRAY_BUFFER)
981  m_boundArrayBuffer = buffer;
982  else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
983  m_boundVertexArrayObject->setElementArrayBuffer(buffer);
984  else {
985  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target");
986  return;
987  }
988 
989  m_context->bindBuffer(target, objectOrZero(buffer));
990  if (buffer)
991  buffer->setTarget(target);
992 }
993 
994 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
995 {
996  UNUSED_PARAM(ec);
997  bool deleted;
998  if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
999  return;
1000  if (deleted)
1001  buffer = 0;
1002  if (target != GraphicsContext3D::FRAMEBUFFER) {
1003  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
1004  return;
1005  }
1006  m_framebufferBinding = buffer;
1007  if (m_drawingBuffer)
1008  m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get()));
1009  if (!m_framebufferBinding && m_drawingBuffer) {
1010  // Instead of binding fb 0, bind the drawing buffer.
1011  m_drawingBuffer->bind();
1012  } else
1013  m_context->bindFramebuffer(target, objectOrZero(buffer));
1014  if (buffer)
1015  buffer->setHasEverBeenBound();
1016  applyStencilTest();
1017 }
1018 
1019 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
1020 {
1021  UNUSED_PARAM(ec);
1022  bool deleted;
1023  if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
1024  return;
1025  if (deleted)
1026  renderBuffer = 0;
1027  if (target != GraphicsContext3D::RENDERBUFFER) {
1028  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target");
1029  return;
1030  }
1031  m_renderbufferBinding = renderBuffer;
1032  m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
1033  if (renderBuffer)
1034  renderBuffer->setHasEverBeenBound();
1035 }
1036 
1037 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
1038 {
1039  UNUSED_PARAM(ec);
1040  bool deleted;
1041  if (!checkObjectToBeBound("bindTexture", texture, deleted))
1042  return;
1043  if (deleted)
1044  texture = 0;
1045  if (texture && texture->getTarget() && texture->getTarget() != target) {
1046  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets");
1047  return;
1048  }
1049  GC3Dint maxLevel = 0;
1050  if (target == GraphicsContext3D::TEXTURE_2D) {
1051  m_textureUnits[m_activeTextureUnit].texture2DBinding = texture;
1052  maxLevel = m_maxTextureLevel;
1053 
1054  if (m_drawingBuffer && !m_activeTextureUnit)
1055  m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
1056 
1057  } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
1058  m_textureUnits[m_activeTextureUnit].textureCubeMapBinding = texture;
1059  maxLevel = m_maxCubeMapTextureLevel;
1060  } else {
1061  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target");
1062  return;
1063  }
1064  m_context->bindTexture(target, objectOrZero(texture));
1065  if (texture)
1066  texture->setTarget(target, maxLevel);
1067 
1068  // Note: previously we used to automatically set the TEXTURE_WRAP_R
1069  // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
1070  // ES 2.0 doesn't expose this flag (a bug in the specification) and
1071  // otherwise the application has no control over the seams in this
1072  // dimension. However, it appears that supporting this properly on all
1073  // platforms is fairly involved (will require a HashMap from texture ID
1074  // in all ports), and we have not had any complaints, so the logic has
1075  // been removed.
1076 }
1077 
1078 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
1079 {
1080  if (isContextLostOrPending())
1081  return;
1082  m_context->blendColor(red, green, blue, alpha);
1083 }
1084 
1085 void WebGLRenderingContext::blendEquation(GC3Denum mode)
 33WebGL1RenderingContext::WebGL1RenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
 34 : WebGLRenderingContextBase(passedCanvas, attributes)
108635{
1087  if (isContextLostOrPending() || !validateBlendEquation("blendEquation", mode))
1088  return;
1089  m_context->blendEquation(mode);
1090 }
1091 
1092 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
1093 {
1094  if (isContextLostOrPending() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha))
1095  return;
1096  m_context->blendEquationSeparate(modeRGB, modeAlpha);
1097 }
1098 
1099 
1100 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
1101 {
1102  if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor))
1103  return;
1104  m_context->blendFunc(sfactor, dfactor);
1105 }
1106 
1107 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
1108 {
1109  // Note: Alpha does not have the same restrictions as RGB.
1110  if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB))
1111  return;
1112  m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
1113 }
1114 
1115 void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
1116 {
1117  UNUSED_PARAM(ec);
1118  if (isContextLostOrPending())
1119  return;
1120  WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1121  if (!buffer)
1122  return;
1123  if (size < 0) {
1124  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
1125  return;
1126  }
1127  if (!size) {
1128  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0");
1129  return;
1130  }
1131  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1132  if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
1133  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1134  return;
1135  }
1136  }
1137 
1138  m_context->moveErrorsToSyntheticErrorList();
1139  m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
1140  if (m_context->moveErrorsToSyntheticErrorList()) {
1141  // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
1142  buffer->disassociateBufferData();
1143  }
1144 }
1145 
1146 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
1147 {
1148  UNUSED_PARAM(ec);
1149  if (isContextLostOrPending())
1150  return;
1151  WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1152  if (!buffer)
1153  return;
1154  if (!data) {
1155  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1156  return;
1157  }
1158  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1159  if (!buffer->associateBufferData(data)) {
1160  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1161  return;
1162  }
1163  }
1164 
1165  m_context->moveErrorsToSyntheticErrorList();
1166  m_context->bufferData(target, data->byteLength(), data->data(), usage);
1167  if (m_context->moveErrorsToSyntheticErrorList()) {
1168  // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
1169  buffer->disassociateBufferData();
1170  }
1171 }
1172 
1173 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
1174 {
1175  UNUSED_PARAM(ec);
1176  if (isContextLostOrPending())
1177  return;
1178  WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1179  if (!buffer)
1180  return;
1181  if (!data) {
1182  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1183  return;
1184  }
1185  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1186  if (!buffer->associateBufferData(data)) {
1187  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1188  return;
1189  }
1190  }
1191 
1192  m_context->moveErrorsToSyntheticErrorList();
1193  m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
1194  if (m_context->moveErrorsToSyntheticErrorList()) {
1195  // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
1196  buffer->disassociateBufferData();
1197  }
1198 }
1199 
1200 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
1201 {
1202  UNUSED_PARAM(ec);
1203  if (isContextLostOrPending())
1204  return;
1205  WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1206  if (!buffer)
1207  return;
1208  if (offset < 0) {
1209  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1210  return;
1211  }
1212  if (!data)
1213  return;
1214  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1215  if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1216  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1217  return;
1218  }
1219  }
1220 
1221  m_context->moveErrorsToSyntheticErrorList();
1222  m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
1223  if (m_context->moveErrorsToSyntheticErrorList()) {
1224  // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
1225  buffer->disassociateBufferData();
1226  }
1227 }
1228 
1229 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
1230 {
1231  UNUSED_PARAM(ec);
1232  if (isContextLostOrPending())
1233  return;
1234  WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1235  if (!buffer)
1236  return;
1237  if (offset < 0) {
1238  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1239  return;
1240  }
1241  if (!data)
1242  return;
1243  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1244  if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1245  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1246  return;
1247  }
1248  }
1249 
1250  m_context->moveErrorsToSyntheticErrorList();
1251  m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
1252  if (m_context->moveErrorsToSyntheticErrorList()) {
1253  // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
1254  buffer->disassociateBufferData();
1255  }
1256 }
1257 
1258 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
1259 {
1260  if (isContextLostOrPending())
1261  return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
1262  if (target != GraphicsContext3D::FRAMEBUFFER) {
1263  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
1264  return 0;
1265  }
1266  if (!m_framebufferBinding || !m_framebufferBinding->object())
1267  return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
1268  const char* reason = "framebuffer incomplete";
1269  GC3Denum result = m_framebufferBinding->checkStatus(&reason);
1270  if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1271  printGLWarningToConsole("checkFramebufferStatus", reason);
1272  return result;
1273  }
1274  result = m_context->checkFramebufferStatus(target);
1275  return result;
1276 }
1277 
1278 void WebGLRenderingContext::clear(GC3Dbitfield mask)
1279 {
1280  if (isContextLostOrPending())
1281  return;
1282  if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1283  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
1284  return;
1285  }
1286  const char* reason = "framebuffer incomplete";
1287  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1288  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
1289  return;
1290  }
1291  if (!clearIfComposited(mask))
1292  m_context->clear(mask);
1293  markContextChanged();
1294 }
1295 
1296 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
1297 {
1298  if (isContextLostOrPending())
1299  return;
1300  if (std::isnan(r))
1301  r = 0;
1302  if (std::isnan(g))
1303  g = 0;
1304  if (std::isnan(b))
1305  b = 0;
1306  if (std::isnan(a))
1307  a = 1;
1308  m_clearColor[0] = r;
1309  m_clearColor[1] = g;
1310  m_clearColor[2] = b;
1311  m_clearColor[3] = a;
1312  m_context->clearColor(r, g, b, a);
1313 }
1314 
1315 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
1316 {
1317  if (isContextLostOrPending())
1318  return;
1319  m_clearDepth = depth;
1320  m_context->clearDepth(depth);
1321 }
1322 
1323 void WebGLRenderingContext::clearStencil(GC3Dint s)
1324 {
1325  if (isContextLostOrPending())
1326  return;
1327  m_clearStencil = s;
1328  m_context->clearStencil(s);
1329 }
1330 
1331 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
1332 {
1333  if (isContextLostOrPending())
1334  return;
1335  m_colorMask[0] = red;
1336  m_colorMask[1] = green;
1337  m_colorMask[2] = blue;
1338  m_colorMask[3] = alpha;
1339  m_context->colorMask(red, green, blue, alpha);
1340 }
1341 
1342 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
1343 {
1344  UNUSED_PARAM(ec);
1345  if (isContextLostOrPending() || !validateWebGLObject("compileShader", shader))
1346  return;
1347  m_context->compileShader(objectOrZero(shader));
1348  GC3Dint value;
1349  m_context->getShaderiv(objectOrZero(shader), GraphicsContext3D::COMPILE_STATUS, &value);
1350  shader->setValid(value);
1351 }
1352 
1353 void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
1354  GC3Dsizei height, GC3Dint border, ArrayBufferView* data)
1355 {
1356  if (isContextLostOrPending())
1357  return;
1358  if (!validateTexFuncLevel("compressedTexImage2D", target, level))
1359  return;
1360 
1361  if (!validateCompressedTexFormat(internalformat)) {
1362  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat");
1363  return;
1364  }
1365  if (border) {
1366  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0");
1367  return;
1368  }
1369  if (!validateCompressedTexDimensions("compressedTexImage2D", target, level, width, height, internalformat))
1370  return;
1371  if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data))
1372  return;
1373 
1374  WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true);
1375  if (!tex)
1376  return;
1377  if (!isGLES2NPOTStrict()) {
1378  if (level && WebGLTexture::isNPOT(width, height)) {
1379  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2");
1380  return;
1381  }
1382  }
1383  m_context->moveErrorsToSyntheticErrorList();
1384  m_context->compressedTexImage2D(target, level, internalformat, width, height,
1385  border, data->byteLength(), data->baseAddress());
1386  if (m_context->moveErrorsToSyntheticErrorList()) {
1387  // The compressedTexImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
1388  tex->markInvalid(target, level);
1389  return;
1390  }
1391 
1392  tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1393  tex->setCompressed();
1394 }
1395 
1396 void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
1397  GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data)
1398 {
1399  if (isContextLostOrPending())
1400  return;
1401  if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
1402  return;
1403  if (!validateCompressedTexFormat(format)) {
1404  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format");
1405  return;
1406  }
1407  if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
1408  return;
1409 
1410  WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true);
1411  if (!tex)
1412  return;
1413 
1414  if (format != tex->getInternalFormat(target, level)) {
1415  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format");
1416  return;
1417  }
1418 
1419  if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex))
1420  return;
1421 
1422  graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset,
1423  width, height, format, data->byteLength(), data->baseAddress());
1424  tex->setCompressed();
 36 m_type = "webgl1";
142537}
142638
1427 bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format)
 39WebGL1RenderingContext::WebGL1RenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
 40 GraphicsContext3D::Attributes attributes) : WebGLRenderingContextBase(passedCanvas, context, attributes)
142841{
1429  if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1430  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
1431  return false;
1432  }
1433  return true;
 42 m_type = "webgl1";
143443}
143544
1436 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
1437 {
1438  if (isContextLostOrPending())
1439  return;
1440  if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
1441  return;
1442  if (!validateSettableTexFormat("copyTexImage2D", internalformat))
1443  return;
1444  WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
1445  if (!tex)
1446  return;
1447  if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1448  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
1449  return;
1450  }
1451  if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1452  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
1453  return;
1454  }
1455  const char* reason = "framebuffer incomplete";
1456  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1457  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
1458  return;
1459  }
1460  clearIfComposited();
1461  if (isResourceSafe()) {
1462  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1463  m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1464  } else {
1465  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1466  GC3Dint clippedX, clippedY;
1467  GC3Dsizei clippedWidth, clippedHeight;
1468  if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1469  m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
1470  internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
1471  if (clippedWidth > 0 && clippedHeight > 0) {
1472  m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
1473  clippedX, clippedY, clippedWidth, clippedHeight);
1474  }
1475  } else
1476  m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1477  }
1478  // FIXME: if the framebuffer is not complete, none of the below should be executed.
1479  tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1480 }
1481 
1482 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1483 {
1484  if (isContextLostOrPending())
1485  return;
1486  if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
1487  return;
1488  WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true);
1489  if (!tex)
1490  return;
1491  if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height))
1492  return;
1493  // Before checking if it is in the range, check if overflow happens first.
1494  if (xoffset + width < 0 || yoffset + height < 0) {
1495  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions");
1496  return;
1497  }
1498  if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
1499  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
1500  return;
1501  }
1502  GC3Denum internalformat = tex->getInternalFormat(target, level);
1503  if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
1504  return;
1505  if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1506  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
1507  return;
1508  }
1509  const char* reason = "framebuffer incomplete";
1510  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1511  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
1512  return;
1513  }
1514  clearIfComposited();
1515  if (isResourceSafe()) {
1516  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1517  m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1518  } else {
1519  GC3Dint clippedX, clippedY;
1520  GC3Dsizei clippedWidth, clippedHeight;
1521  if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1522  GC3Denum format = tex->getInternalFormat(target, level);
1523  GC3Denum type = tex->getType(target, level);
1524  std::unique_ptr<unsigned char[]> zero;
1525  if (width && height) {
1526  unsigned int size;
1527  GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
1528  if (error != GraphicsContext3D::NO_ERROR) {
1529  synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
1530  return;
1531  }
1532  zero = std::make_unique<unsigned char[]>(size);
1533  if (!zero) {
1534  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory");
1535  return;
1536  }
1537  memset(zero.get(), 0, size);
1538  }
1539  m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
1540  if (clippedWidth > 0 && clippedHeight > 0) {
1541  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1542  m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
1543  clippedX, clippedY, clippedWidth, clippedHeight);
1544  }
1545  } else {
1546  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1547  m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1548  }
1549  }
1550 }
1551 
1552 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1553 {
1554  if (isContextLostOrPending())
1555  return nullptr;
1556  RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1557  addSharedObject(o.get());
1558  return o;
1559 }
1560 
1561 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1562 {
1563  if (isContextLostOrPending())
1564  return nullptr;
1565  RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1566  addContextObject(o.get());
1567  return o;
1568 }
1569 
1570 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1571 {
1572  if (isContextLostOrPending())
1573  return nullptr;
1574  RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1575  addSharedObject(o.get());
1576  return o;
1577 }
1578 
1579 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1580 {
1581  if (isContextLostOrPending())
1582  return nullptr;
1583  RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1584  addSharedObject(o.get());
1585  return o;
1586 }
1587 
1588 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1589 {
1590  if (isContextLostOrPending())
1591  return nullptr;
1592  RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1593  addSharedObject(o.get());
1594  return o;
1595 }
1596 
1597 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
1598 {
1599  UNUSED_PARAM(ec);
1600  if (isContextLostOrPending())
1601  return nullptr;
1602  if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
1603  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type");
1604  return nullptr;
1605  }
1606 
1607  RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1608  addSharedObject(o.get());
1609  return o;
1610 }
1611 
1612 void WebGLRenderingContext::cullFace(GC3Denum mode)
1613 {
1614  if (isContextLostOrPending())
1615  return;
1616  m_context->cullFace(mode);
1617 }
1618 
1619 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1620 {
1621  if (isContextLostOrPending() || !object)
1622  return false;
1623  if (!object->validate(contextGroup(), this)) {
1624  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context");
1625  return false;
1626  }
1627  if (object->object())
1628  // We need to pass in context here because we want
1629  // things in this context unbound.
1630  object->deleteObject(graphicsContext3D());
1631  return true;
1632 }
1633 
1634 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1635 {
1636  if (!deleteObject(buffer))
1637  return;
1638  if (m_boundArrayBuffer == buffer)
1639  m_boundArrayBuffer = 0;
1640 
1641  m_boundVertexArrayObject->unbindBuffer(buffer);
1642 }
1643 
1644 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1645 {
1646  if (!deleteObject(framebuffer))
1647  return;
1648  if (framebuffer == m_framebufferBinding) {
1649  m_framebufferBinding = 0;
1650  if (m_drawingBuffer) {
1651  m_drawingBuffer->setFramebufferBinding(0);
1652  // Have to call bindFramebuffer here to bind back to internal fbo.
1653  m_drawingBuffer->bind();
1654  } else
1655  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
1656  }
1657 }
1658 
1659 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1660 {
1661  deleteObject(program);
1662  // We don't reset m_currentProgram to 0 here because the deletion of the
1663  // current program is delayed.
1664 }
1665 
1666 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1667 {
1668  if (!deleteObject(renderbuffer))
1669  return;
1670  if (renderbuffer == m_renderbufferBinding)
1671  m_renderbufferBinding = 0;
1672  if (m_framebufferBinding)
1673  m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
1674 }
1675 
1676 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1677 {
1678  deleteObject(shader);
1679 }
1680 
1681 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1682 {
1683  if (!deleteObject(texture))
1684  return;
1685  for (size_t i = 0; i < m_textureUnits.size(); ++i) {
1686  if (texture == m_textureUnits[i].texture2DBinding)
1687  m_textureUnits[i].texture2DBinding = nullptr;
1688  if (texture == m_textureUnits[i].textureCubeMapBinding)
1689  m_textureUnits[i].textureCubeMapBinding = nullptr;
1690  }
1691  if (m_framebufferBinding)
1692  m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
1693 }
1694 
1695 void WebGLRenderingContext::depthFunc(GC3Denum func)
1696 {
1697  if (isContextLostOrPending())
1698  return;
1699  m_context->depthFunc(func);
1700 }
1701 
1702 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1703 {
1704  if (isContextLostOrPending())
1705  return;
1706  m_depthMask = flag;
1707  m_context->depthMask(flag);
1708 }
1709 
1710 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1711 {
1712  if (isContextLostOrPending())
1713  return;
1714  if (zNear > zFar) {
1715  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar");
1716  return;
1717  }
1718  m_context->depthRange(zNear, zFar);
1719 }
1720 
1721 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
1722 {
1723  UNUSED_PARAM(ec);
1724  if (isContextLostOrPending() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader))
1725  return;
1726  if (!program->detachShader(shader)) {
1727  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
1728  return;
1729  }
1730  m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1731  shader->onDetached(graphicsContext3D());
1732 }
1733 
1734 void WebGLRenderingContext::disable(GC3Denum cap)
1735 {
1736  if (isContextLostOrPending() || !validateCapability("disable", cap))
1737  return;
1738  if (cap == GraphicsContext3D::STENCIL_TEST) {
1739  m_stencilEnabled = false;
1740  applyStencilTest();
1741  return;
1742  }
1743  if (cap == GraphicsContext3D::SCISSOR_TEST) {
1744  m_scissorEnabled = false;
1745  if (m_drawingBuffer)
1746  m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
1747  }
1748  m_context->disable(cap);
1749 }
1750 
1751 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1752 {
1753  UNUSED_PARAM(ec);
1754  if (isContextLostOrPending())
1755  return;
1756  if (index >= m_maxVertexAttribs) {
1757  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range");
1758  return;
1759  }
1760 
1761  WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1762  state.enabled = false;
1763 
1764  if (index > 0 || isGLES2Compliant())
1765  m_context->disableVertexAttribArray(index);
1766 }
1767 
1768 bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
1769 {
1770  RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1771 
1772  if (!elementArrayBuffer)
1773  return false;
1774 
1775  if (offset < 0)
1776  return false;
1777 
1778  if (type == GraphicsContext3D::UNSIGNED_INT) {
1779  // For an unsigned int array, offset must be divisible by 4 for alignment reasons.
1780  if (offset % 4)
1781  return false;
1782 
1783  // Make uoffset an element offset.
1784  offset /= 4;
1785 
1786  GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 4;
1787  if (offset > n || count > n - offset)
1788  return false;
1789  } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1790  // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1791  if (offset % 2)
1792  return false;
1793 
1794  // Make uoffset an element offset.
1795  offset /= 2;
1796 
1797  GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
1798  if (offset > n || count > n - offset)
1799  return false;
1800  } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1801  GC3Dsizeiptr n = elementArrayBuffer->byteLength();
1802  if (offset > n || count > n - offset)
1803  return false;
1804  }
1805  return true;
1806 }
1807 
1808 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
1809 {
1810  // Performs conservative validation by caching a maximum index of
1811  // the given type per element array buffer. If all of the bound
1812  // array buffers have enough elements to satisfy that maximum
1813  // index, skips the expensive per-draw-call iteration in
1814  // validateIndexArrayPrecise.
1815 
1816  RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1817 
1818  if (!elementArrayBuffer)
1819  return false;
1820 
1821  GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1822  // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1823  if (!numElements)
1824  return false;
1825  const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1826  ASSERT(buffer);
1827 
1828  int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1829  if (maxIndex < 0) {
1830  // Compute the maximum index in the entire buffer for the given type of index.
1831  switch (type) {
1832  case GraphicsContext3D::UNSIGNED_BYTE: {
1833  const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1834  for (GC3Dsizeiptr i = 0; i < numElements; i++)
1835  maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1836  break;
1837  }
1838  case GraphicsContext3D::UNSIGNED_SHORT: {
1839  numElements /= sizeof(GC3Dushort);
1840  const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1841  for (GC3Dsizeiptr i = 0; i < numElements; i++)
1842  maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1843  break;
1844  }
1845  case GraphicsContext3D::UNSIGNED_INT: {
1846  if (!m_oesElementIndexUint)
1847  return false;
1848  numElements /= sizeof(GC3Duint);
1849  const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
1850  for (GC3Dsizeiptr i = 0; i < numElements; i++)
1851  maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1852  break;
1853  }
1854  default:
1855  return false;
1856  }
1857  elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1858  }
1859 
1860  if (maxIndex >= 0) {
1861  // The number of required elements is one more than the maximum
1862  // index that will be accessed.
1863  numElementsRequired = maxIndex + 1;
1864  return true;
1865  }
1866 
1867  return false;
1868 }
1869 
1870 bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired)
1871 {
1872  ASSERT(count >= 0 && offset >= 0);
1873  unsigned lastIndex = 0;
1874 
1875  RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1876 
1877  if (!elementArrayBuffer)
1878  return false;
1879 
1880  if (!count) {
1881  numElementsRequired = 0;
1882  return true;
1883  }
1884 
1885  if (!elementArrayBuffer->elementArrayBuffer())
1886  return false;
1887 
1888  unsigned long uoffset = offset;
1889  unsigned long n = count;
1890 
1891  if (type == GraphicsContext3D::UNSIGNED_INT) {
1892  // Make uoffset an element offset.
1893  uoffset /= sizeof(GC3Duint);
1894  const GC3Duint* p = static_cast<const GC3Duint*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1895  while (n-- > 0) {
1896  if (*p > lastIndex)
1897  lastIndex = *p;
1898  ++p;
1899  }
1900  } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1901  // Make uoffset an element offset.
1902  uoffset /= sizeof(GC3Dushort);
1903  const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1904  while (n-- > 0) {
1905  if (*p > lastIndex)
1906  lastIndex = *p;
1907  ++p;
1908  }
1909  } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1910  const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1911  while (n-- > 0) {
1912  if (*p > lastIndex)
1913  lastIndex = *p;
1914  ++p;
1915  }
1916  }
1917 
1918  // Then set the last index in the index array and make sure it is valid.
1919  numElementsRequired = lastIndex + 1;
1920  return numElementsRequired > 0;
1921 }
1922 
1923 bool WebGLRenderingContext::validateVertexAttributes(unsigned elementCount, unsigned primitiveCount)
1924 {
1925  if (!m_currentProgram)
1926  return false;
1927 
1928  // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1929  for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
1930  if (!m_boundVertexArrayObject->getVertexAttribState(i).validateBinding())
1931  return false;
1932  }
1933 
1934  if (elementCount <= 0)
1935  return true;
1936 
1937 
1938  // Look in each consumed vertex attrib (by the current program).
1939  bool sawNonInstancedAttrib = false;
1940  bool sawEnabledAttrib = false;
1941  int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1942  for (int i = 0; i < numActiveAttribLocations; ++i) {
1943  int loc = m_currentProgram->getActiveAttribLocation(i);
1944  if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
1945  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
1946  if (state.enabled) {
1947  sawEnabledAttrib = true;
1948  // Avoid off-by-one errors in numElements computation.
1949  // For the last element, we will only touch the data for the
1950  // element and nothing beyond it.
1951  int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
1952  unsigned numElements = 0;
1953  ASSERT(state.stride > 0);
1954  if (bytesRemaining >= state.bytesPerElement)
1955  numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1956  if (!state.divisor)
1957  sawNonInstancedAttrib = true;
1958  if ((!state.divisor && elementCount > numElements) || (state.divisor && primitiveCount > numElements))
1959  return false;
1960  }
1961  }
1962  }
1963 
1964  if (!sawNonInstancedAttrib && sawEnabledAttrib)
1965  return false;
1966 
1967  return true;
1968 }
1969 
1970 bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object)
1971 {
1972  if (!object || !object->object()) {
1973  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted");
1974  return false;
1975  }
1976  if (!object->validate(contextGroup(), this)) {
1977  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context");
1978  return false;
1979  }
1980  return true;
1981 }
1982 
1983 bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
1984 {
1985  if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
1986  return false;
1987 
1988  if (!validateStencilSettings(functionName))
1989  return false;
1990 
1991  if (first < 0 || count < 0) {
1992  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0");
1993  return false;
1994  }
1995 
1996  if (!count) {
1997  markContextChanged();
1998  return false;
1999  }
2000 
2001  if (primcount < 0) {
2002  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
2003  return false;
2004  }
2005 
2006  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
2007  // Ensure we have a valid rendering state
2008  Checked<GC3Dint, RecordOverflow> checkedFirst(first);
2009  Checked<GC3Dint, RecordOverflow> checkedCount(count);
2010  Checked<GC3Dint, RecordOverflow> checkedSum = checkedFirst + checkedCount;
2011  Checked<GC3Dint, RecordOverflow> checkedPrimCount(primcount);
2012  if (checkedSum.hasOverflowed() || checkedPrimCount.hasOverflowed() || !validateVertexAttributes(checkedSum.unsafeGet(), checkedPrimCount.unsafeGet())) {
2013  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
2014  return false;
2015  }
2016  } else {
2017  if (!validateVertexAttributes(0)) {
2018  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
2019  return false;
2020  }
2021  }
2022 
2023  const char* reason = "framebuffer incomplete";
2024  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
2025  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
2026  return false;
2027  }
2028 
2029  return true;
2030 }
2031 
2032 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
2033 {
2034  UNUSED_PARAM(ec);
2035 
2036  if (!validateDrawArrays("drawArrays", mode, first, count, 0))
2037  return;
2038 
2039  clearIfComposited();
2040 
2041  bool vertexAttrib0Simulated = false;
2042  if (!isGLES2Compliant())
2043  vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
2044  if (!isGLES2NPOTStrict())
2045  checkTextureCompleteness("drawArrays", true);
2046  m_context->drawArrays(mode, first, count);
2047  if (!isGLES2Compliant() && vertexAttrib0Simulated)
2048  restoreStatesAfterVertexAttrib0Simulation();
2049  if (!isGLES2NPOTStrict())
2050  checkTextureCompleteness("drawArrays", false);
2051  markContextChanged();
2052 }
2053 
2054 bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements)
2055 {
2056  if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
2057  return false;
2058 
2059  if (!validateStencilSettings(functionName))
2060  return false;
2061 
2062  switch (type) {
2063  case GraphicsContext3D::UNSIGNED_BYTE:
2064  case GraphicsContext3D::UNSIGNED_SHORT:
2065  break;
2066  case GraphicsContext3D::UNSIGNED_INT:
2067  if (m_oesElementIndexUint)
2068  break;
2069  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
2070  return false;
2071  default:
2072  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
2073  return false;
2074  }
2075 
2076  if (count < 0 || offset < 0) {
2077  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0");
2078  return false;
2079  }
2080 
2081  if (!count) {
2082  markContextChanged();
2083  return false;
2084  }
2085 
2086  if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
2087  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound");
2088  return false;
2089  }
2090 
2091  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
2092  // Ensure we have a valid rendering state
2093  if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
2094  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "request out of bounds for current ELEMENT_ARRAY_BUFFER");
2095  return false;
2096  }
2097  if (!count)
2098  return false;
2099  if (!validateIndexArrayConservative(type, numElements) || !validateVertexAttributes(numElements)) {
2100  if (!validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements) || !validateVertexAttributes(numElements)) {
2101  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
2102  return false;
2103  }
2104  }
2105  } else {
2106  if (!validateVertexAttributes(0)) {
2107  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
2108  return false;
2109  }
2110  }
2111 
2112  const char* reason = "framebuffer incomplete";
2113  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
2114  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
2115  return false;
2116  }
2117 
2118  return true;
2119 }
2120 
2121 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
2122 {
2123  UNUSED_PARAM(ec);
2124 
2125  unsigned numElements = 0;
2126  if (!validateDrawElements("drawElements", mode, count, type, offset, numElements))
2127  return;
2128 
2129  clearIfComposited();
2130 
2131  bool vertexAttrib0Simulated = false;
2132  if (!isGLES2Compliant()) {
2133  if (!numElements)
2134  validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
2135  vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
2136  }
2137  if (!isGLES2NPOTStrict())
2138  checkTextureCompleteness("drawElements", true);
2139  m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
2140  if (!isGLES2Compliant() && vertexAttrib0Simulated)
2141  restoreStatesAfterVertexAttrib0Simulation();
2142  if (!isGLES2NPOTStrict())
2143  checkTextureCompleteness("drawElements", false);
2144  markContextChanged();
2145 }
2146 
2147 void WebGLRenderingContext::enable(GC3Denum cap)
2148 {
2149  if (isContextLostOrPending() || !validateCapability("enable", cap))
2150  return;
2151  if (cap == GraphicsContext3D::STENCIL_TEST) {
2152  m_stencilEnabled = true;
2153  applyStencilTest();
2154  return;
2155  }
2156  if (cap == GraphicsContext3D::SCISSOR_TEST) {
2157  m_scissorEnabled = true;
2158  if (m_drawingBuffer)
2159  m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
2160  }
2161  m_context->enable(cap);
2162 }
2163 
2164 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
2165 {
2166  UNUSED_PARAM(ec);
2167  if (isContextLostOrPending())
2168  return;
2169  if (index >= m_maxVertexAttribs) {
2170  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range");
2171  return;
2172  }
2173 
2174  WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
2175  state.enabled = true;
2176 
2177  m_context->enableVertexAttribArray(index);
2178 }
2179 
2180 void WebGLRenderingContext::finish()
2181 {
2182  if (isContextLostOrPending())
2183  return;
2184  m_context->finish();
2185 }
2186 
2187 void WebGLRenderingContext::flush()
2188 {
2189  if (isContextLostOrPending())
2190  return;
2191  m_context->flush();
2192 }
2193 
2194 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
2195 {
2196  UNUSED_PARAM(ec);
2197  if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment))
2198  return;
2199  if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
2200  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target");
2201  return;
2202  }
2203  if (buffer && !buffer->validate(contextGroup(), this)) {
2204  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
2205  return;
2206  }
2207  // Don't allow the default framebuffer to be mutated; all current
2208  // implementations use an FBO internally in place of the default
2209  // FBO.
2210  if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2211  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
2212  return;
2213  }
2214  Platform3DObject bufferObject = objectOrZero(buffer);
2215  switch (attachment) {
2216  case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2217  m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
2218  m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
2219  break;
2220  default:
2221  m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2222  }
2223  m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
2224  applyStencilTest();
2225 }
2226 
2227 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
2228 {
2229  UNUSED_PARAM(ec);
2230  if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
2231  return;
2232  if (level) {
2233  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
2234  return;
2235  }
2236  if (texture && !texture->validate(contextGroup(), this)) {
2237  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
2238  return;
2239  }
2240  // Don't allow the default framebuffer to be mutated; all current
2241  // implementations use an FBO internally in place of the default
2242  // FBO.
2243  if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2244  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
2245  return;
2246  }
2247  Platform3DObject textureObject = objectOrZero(texture);
2248  switch (attachment) {
2249  case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2250  m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level);
2251  m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level);
2252  break;
2253  case GraphicsContext3D::DEPTH_ATTACHMENT:
2254  m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2255  break;
2256  case GraphicsContext3D::STENCIL_ATTACHMENT:
2257  m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2258  break;
2259  default:
2260  m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2261  }
2262  m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
2263  applyStencilTest();
2264 }
2265 
2266 void WebGLRenderingContext::frontFace(GC3Denum mode)
2267 {
2268  if (isContextLostOrPending())
2269  return;
2270  m_context->frontFace(mode);
2271 }
2272 
2273 void WebGLRenderingContext::generateMipmap(GC3Denum target)
2274 {
2275  if (isContextLostOrPending())
2276  return;
2277  WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
2278  if (!tex)
2279  return;
2280  if (!tex->canGenerateMipmaps()) {
2281  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size");
2282  return;
2283  }
2284  // FIXME: https://bugs.webkit.org/show_bug.cgi?id=123916. Compressed textures should be allowed in WebGL 2:
2285  if (tex->isCompressed()) {
2286  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture");
2287  return;
2288  }
2289  if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
2290  return;
2291 
2292  // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
2293  // on Mac. Remove the hack once this driver bug is fixed.
2294 #if OS(DARWIN)
2295  bool needToResetMinFilter = false;
2296  if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
2297  m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
2298  needToResetMinFilter = true;
2299  }
2300 #endif
2301  m_context->generateMipmap(target);
2302 #if OS(DARWIN)
2303  if (needToResetMinFilter)
2304  m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
2305 #endif
2306  tex->generateMipmapLevelInfo();
2307 }
2308 
2309 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2310 {
2311  UNUSED_PARAM(ec);
2312  if (isContextLostOrPending() || !validateWebGLObject("getActiveAttrib", program))
2313  return nullptr;
2314  ActiveInfo info;
2315  if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
2316  return nullptr;
2317 
2318  LOG(WebGL, "Returning active attribute %d: %s", index, info.name.utf8().data());
2319 
2320  return WebGLActiveInfo::create(info.name, info.type, info.size);
2321 }
2322 
2323 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2324 {
2325  UNUSED_PARAM(ec);
2326  if (isContextLostOrPending() || !validateWebGLObject("getActiveUniform", program))
2327  return 0;
2328  ActiveInfo info;
2329  if (!m_context->getActiveUniform(objectOrZero(program), index, info))
2330  return nullptr;
2331  if (!isGLES2Compliant())
2332  if (info.size > 1 && !info.name.endsWith("[0]"))
2333  info.name.append("[0]");
2334 
2335  LOG(WebGL, "Returning active uniform %d: %s", index, info.name.utf8().data());
2336 
2337  return WebGLActiveInfo::create(info.name, info.type, info.size);
2338 }
2339 
2340 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader>>& shaderObjects, ExceptionCode& ec)
2341 {
2342  UNUSED_PARAM(ec);
2343  shaderObjects.clear();
2344  if (isContextLostOrPending() || !validateWebGLObject("getAttachedShaders", program))
2345  return false;
2346 
2347  const GC3Denum shaderType[] = {
2348  GraphicsContext3D::VERTEX_SHADER,
2349  GraphicsContext3D::FRAGMENT_SHADER
2350  };
2351  for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
2352  WebGLShader* shader = program->getAttachedShader(shaderType[i]);
2353  if (shader)
2354  shaderObjects.append(shader);
2355  }
2356  return true;
2357 }
2358 
2359 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
2360 {
2361  if (isContextLostOrPending() || !validateWebGLObject("getAttribLocation", program))
2362  return -1;
2363  if (!validateLocationLength("getAttribLocation", name))
2364  return -1;
2365  if (!validateString("getAttribLocation", name))
2366  return -1;
2367  if (isPrefixReserved(name))
2368  return -1;
2369  if (!program->getLinkStatus()) {
2370  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked");
2371  return -1;
2372  }
2373  return m_context->getAttribLocation(objectOrZero(program), name);
2374 }
2375 
2376 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2377 {
2378  UNUSED_PARAM(ec);
2379  if (isContextLostOrPending())
2380  return WebGLGetInfo();
2381  if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
2382  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
2383  return WebGLGetInfo();
2384  }
2385 
2386  if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
2387  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
2388  return WebGLGetInfo();
2389  }
2390 
2391  GC3Dint value = 0;
2392  m_context->getBufferParameteriv(target, pname, &value);
2393  if (pname == GraphicsContext3D::BUFFER_SIZE)
2394  return WebGLGetInfo(value);
2395  return WebGLGetInfo(static_cast<unsigned int>(value));
2396 }
2397 
2398 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
2399 {
2400  if (isContextLostOrPending())
2401  return nullptr;
2402  // We always need to return a new WebGLContextAttributes object to
2403  // prevent the user from mutating any cached version.
2404 
2405  // Also, we need to enforce requested values of "false" for depth
2406  // and stencil, regardless of the properties of the underlying
2407  // GraphicsContext3D or DrawingBuffer.
2408  RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
2409  if (!m_attributes.depth)
2410  attributes->setDepth(false);
2411  if (!m_attributes.stencil)
2412  attributes->setStencil(false);
2413  if (m_drawingBuffer) {
2414  // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(),
2415  // but it makes its own determination of whether multisampling is supported.
2416  attributes->setAntialias(m_drawingBuffer->multisample());
2417  }
2418  return attributes.release();
2419 }
2420 
2421 GC3Denum WebGLRenderingContext::getError()
2422 {
2423  if (m_isPendingPolicyResolution)
2424  return GraphicsContext3D::NO_ERROR;
2425  return m_context->getError();
2426 }
2427 
2428 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
2429 {
2430  if (isContextLostOrPending())
2431  return nullptr;
2432 
2433  if (equalIgnoringCase(name, "EXT_shader_texture_lod")
2434  && (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))) {
2435  if (!m_extShaderTextureLOD) {
2436  m_context->getExtensions()->ensureEnabled("GL_EXT_shader_texture_lod");
2437  m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(this);
2438  }
2439  return m_extShaderTextureLOD.get();
2440  }
2441  if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic")
2442  && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
2443  if (!m_extTextureFilterAnisotropic) {
2444  m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
2445  m_extTextureFilterAnisotropic = std::make_unique<EXTTextureFilterAnisotropic>(this);
2446  }
2447  return m_extTextureFilterAnisotropic.get();
2448  }
2449  if (equalIgnoringCase(name, "OES_standard_derivatives")
2450  && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
2451  if (!m_oesStandardDerivatives) {
2452  m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
2453  m_oesStandardDerivatives = std::make_unique<OESStandardDerivatives>(this);
2454  }
2455  return m_oesStandardDerivatives.get();
2456  }
2457  if (equalIgnoringCase(name, "OES_texture_float")
2458  && m_context->getExtensions()->supports("GL_OES_texture_float")) {
2459  if (!m_oesTextureFloat) {
2460  m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
2461  m_oesTextureFloat = std::make_unique<OESTextureFloat>(this);
2462  }
2463  return m_oesTextureFloat.get();
2464  }
2465  if (equalIgnoringCase(name, "OES_texture_float_linear")
2466  && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) {
2467  if (!m_oesTextureFloatLinear) {
2468  m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear");
2469  m_oesTextureFloatLinear = std::make_unique<OESTextureFloatLinear>(this);
2470  }
2471  return m_oesTextureFloatLinear.get();
2472  }
2473  if (equalIgnoringCase(name, "OES_texture_half_float")
2474  && m_context->getExtensions()->supports("GL_OES_texture_half_float")) {
2475  if (!m_oesTextureHalfFloat) {
2476  m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float");
2477  m_oesTextureHalfFloat = std::make_unique<OESTextureHalfFloat>(this);
2478  }
2479  return m_oesTextureHalfFloat.get();
2480  }
2481  if (equalIgnoringCase(name, "OES_texture_half_float_linear")
2482  && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) {
2483  if (!m_oesTextureHalfFloatLinear) {
2484  m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear");
2485  m_oesTextureHalfFloatLinear = std::make_unique<OESTextureHalfFloatLinear>(this);
2486  }
2487  return m_oesTextureHalfFloatLinear.get();
2488  }
2489  if (equalIgnoringCase(name, "OES_vertex_array_object")
2490  && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
2491  if (!m_oesVertexArrayObject) {
2492  m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
2493  m_oesVertexArrayObject = std::make_unique<OESVertexArrayObject>(this);
2494  }
2495  return m_oesVertexArrayObject.get();
2496  }
2497  if (equalIgnoringCase(name, "OES_element_index_uint")
2498  && m_context->getExtensions()->supports("GL_OES_element_index_uint")) {
2499  if (!m_oesElementIndexUint) {
2500  m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint");
2501  m_oesElementIndexUint = std::make_unique<OESElementIndexUint>(this);
2502  }
2503  return m_oesElementIndexUint.get();
2504  }
2505  if (equalIgnoringCase(name, "WEBGL_lose_context")) {
2506  if (!m_webglLoseContext)
2507  m_webglLoseContext = std::make_unique<WebGLLoseContext>(this);
2508  return m_webglLoseContext.get();
2509  }
2510  if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_atc"))
2511  && WebGLCompressedTextureATC::supported(this)) {
2512  if (!m_webglCompressedTextureATC)
2513  m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(this);
2514  return m_webglCompressedTextureATC.get();
2515  }
2516  if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc"))
2517  && WebGLCompressedTexturePVRTC::supported(this)) {
2518  if (!m_webglCompressedTexturePVRTC)
2519  m_webglCompressedTexturePVRTC = std::make_unique<WebGLCompressedTexturePVRTC>(this);
2520  return m_webglCompressedTexturePVRTC.get();
2521  }
2522  if (equalIgnoringCase(name, "WEBGL_compressed_texture_s3tc")
2523  && WebGLCompressedTextureS3TC::supported(this)) {
2524  if (!m_webglCompressedTextureS3TC)
2525  m_webglCompressedTextureS3TC = std::make_unique<WebGLCompressedTextureS3TC>(this);
2526  return m_webglCompressedTextureS3TC.get();
2527  }
2528  if (equalIgnoringCase(name, "WEBGL_depth_texture")
2529  && WebGLDepthTexture::supported(graphicsContext3D())) {
2530  if (!m_webglDepthTexture) {
2531  m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
2532  m_webglDepthTexture = std::make_unique<WebGLDepthTexture>(this);
2533  }
2534  return m_webglDepthTexture.get();
2535  }
2536  if (equalIgnoringCase(name, "WEBGL_draw_buffers") && supportsDrawBuffers()) {
2537  if (!m_webglDrawBuffers) {
2538  m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
2539  m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(this);
2540  }
2541  return m_webglDrawBuffers.get();
2542  }
2543  if (equalIgnoringCase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) {
2544  if (!m_angleInstancedArrays) {
2545  m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays");
2546  m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(this);
2547  }
2548  return m_angleInstancedArrays.get();
2549  }
2550  if (allowPrivilegedExtensions()) {
2551  if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) {
2552  if (!m_webglDebugRendererInfo)
2553  m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(this);
2554  return m_webglDebugRendererInfo.get();
2555  }
2556  if (equalIgnoringCase(name, "WEBGL_debug_shaders")
2557  && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
2558  if (!m_webglDebugShaders)
2559  m_webglDebugShaders = std::make_unique<WebGLDebugShaders>(this);
2560  return m_webglDebugShaders.get();
2561  }
2562  }
2563 
2564  return nullptr;
2565 }
2566 
2567 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
2568 {
2569  UNUSED_PARAM(ec);
2570  if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
2571  return WebGLGetInfo();
2572 
2573  if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2574  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
2575  return WebGLGetInfo();
2576  }
2577 
2578  WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
2579  if (!object) {
2580  if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2581  return WebGLGetInfo(GraphicsContext3D::NONE);
2582  // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
2583  // specifies INVALID_OPERATION.
2584  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
2585  return WebGLGetInfo();
2586  }
2587 
2588  ASSERT(object->isTexture() || object->isRenderbuffer());
2589  if (object->isTexture()) {
2590  switch (pname) {
2591  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2592  return WebGLGetInfo(GraphicsContext3D::TEXTURE);
2593  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2594  return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
2595  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2596  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2597  {
2598  GC3Dint value = 0;
2599  m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
2600  return WebGLGetInfo(value);
2601  }
2602  default:
2603  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
2604  return WebGLGetInfo();
2605  }
2606  } else {
2607  switch (pname) {
2608  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2609  return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
2610  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2611  return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
2612  default:
2613  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
2614  return WebGLGetInfo();
2615  }
2616  }
2617 }
2618 
2619 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
2620 {
2621  UNUSED_PARAM(ec);
2622  if (isContextLostOrPending())
2623  return WebGLGetInfo();
2624  const int intZero = 0;
2625  switch (pname) {
2626  case GraphicsContext3D::ACTIVE_TEXTURE:
2627  return getUnsignedIntParameter(pname);
2628  case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2629  return getWebGLFloatArrayParameter(pname);
2630  case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2631  return getWebGLFloatArrayParameter(pname);
2632  case GraphicsContext3D::ALPHA_BITS:
2633  return getIntParameter(pname);
2634  case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2635  return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2636  case GraphicsContext3D::BLEND:
2637  return getBooleanParameter(pname);
2638  case GraphicsContext3D::BLEND_COLOR:
2639  return getWebGLFloatArrayParameter(pname);
2640  case GraphicsContext3D::BLEND_DST_ALPHA:
2641  return getUnsignedIntParameter(pname);
2642  case GraphicsContext3D::BLEND_DST_RGB:
2643  return getUnsignedIntParameter(pname);
2644  case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2645  return getUnsignedIntParameter(pname);
2646  case GraphicsContext3D::BLEND_EQUATION_RGB:
2647  return getUnsignedIntParameter(pname);
2648  case GraphicsContext3D::BLEND_SRC_ALPHA:
2649  return getUnsignedIntParameter(pname);
2650  case GraphicsContext3D::BLEND_SRC_RGB:
2651  return getUnsignedIntParameter(pname);
2652  case GraphicsContext3D::BLUE_BITS:
2653  return getIntParameter(pname);
2654  case GraphicsContext3D::COLOR_CLEAR_VALUE:
2655  return getWebGLFloatArrayParameter(pname);
2656  case GraphicsContext3D::COLOR_WRITEMASK:
2657  return getBooleanArrayParameter(pname);
2658  case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2659  return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()));
2660  case GraphicsContext3D::CULL_FACE:
2661  return getBooleanParameter(pname);
2662  case GraphicsContext3D::CULL_FACE_MODE:
2663  return getUnsignedIntParameter(pname);
2664  case GraphicsContext3D::CURRENT_PROGRAM:
2665  return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2666  case GraphicsContext3D::DEPTH_BITS:
2667  if (!m_framebufferBinding && !m_attributes.depth)
2668  return WebGLGetInfo(intZero);
2669  return getIntParameter(pname);
2670  case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2671  return getFloatParameter(pname);
2672  case GraphicsContext3D::DEPTH_FUNC:
2673  return getUnsignedIntParameter(pname);
2674  case GraphicsContext3D::DEPTH_RANGE:
2675  return getWebGLFloatArrayParameter(pname);
2676  case GraphicsContext3D::DEPTH_TEST:
2677  return getBooleanParameter(pname);
2678  case GraphicsContext3D::DEPTH_WRITEMASK:
2679  return getBooleanParameter(pname);
2680  case GraphicsContext3D::DITHER:
2681  return getBooleanParameter(pname);
2682  case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2683  return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
2684  case GraphicsContext3D::FRAMEBUFFER_BINDING:
2685  return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2686  case GraphicsContext3D::FRONT_FACE:
2687  return getUnsignedIntParameter(pname);
2688  case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2689  return getUnsignedIntParameter(pname);
2690  case GraphicsContext3D::GREEN_BITS:
2691  return getIntParameter(pname);
2692  case GraphicsContext3D::LINE_WIDTH:
2693  return getFloatParameter(pname);
2694  case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2695  return getIntParameter(pname);
2696  case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2697  return getIntParameter(pname);
2698  case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2699  return getIntParameter(pname);
2700  case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2701  return getIntParameter(pname);
2702  case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2703  return getIntParameter(pname);
2704  case GraphicsContext3D::MAX_TEXTURE_SIZE:
2705  return getIntParameter(pname);
2706  case GraphicsContext3D::MAX_VARYING_VECTORS:
2707  return getIntParameter(pname);
2708  case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2709  return getIntParameter(pname);
2710  case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2711  return getIntParameter(pname);
2712  case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2713  return getIntParameter(pname);
2714  case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2715  return getWebGLIntArrayParameter(pname);
2716  case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2717  // FIXME: should we always return 0 for this?
2718  return getIntParameter(pname);
2719  case GraphicsContext3D::PACK_ALIGNMENT:
2720  return getIntParameter(pname);
2721  case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2722  return getFloatParameter(pname);
2723  case GraphicsContext3D::POLYGON_OFFSET_FILL:
2724  return getBooleanParameter(pname);
2725  case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2726  return getFloatParameter(pname);
2727  case GraphicsContext3D::RED_BITS:
2728  return getIntParameter(pname);
2729  case GraphicsContext3D::RENDERBUFFER_BINDING:
2730  return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
2731  case GraphicsContext3D::RENDERER:
2732  return WebGLGetInfo(String("WebKit WebGL"));
2733  case GraphicsContext3D::SAMPLE_BUFFERS:
2734  return getIntParameter(pname);
2735  case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2736  return getBooleanParameter(pname);
2737  case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2738  return getFloatParameter(pname);
2739  case GraphicsContext3D::SAMPLES:
2740  return getIntParameter(pname);
2741  case GraphicsContext3D::SCISSOR_BOX:
2742  return getWebGLIntArrayParameter(pname);
2743  case GraphicsContext3D::SCISSOR_TEST:
2744  return getBooleanParameter(pname);
2745  case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2746  return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
2747  case GraphicsContext3D::STENCIL_BACK_FAIL:
2748  return getUnsignedIntParameter(pname);
2749  case GraphicsContext3D::STENCIL_BACK_FUNC:
2750  return getUnsignedIntParameter(pname);
2751  case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2752  return getUnsignedIntParameter(pname);
2753  case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2754  return getUnsignedIntParameter(pname);
2755  case GraphicsContext3D::STENCIL_BACK_REF:
2756  return getIntParameter(pname);
2757  case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2758  return getUnsignedIntParameter(pname);
2759  case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2760  return getUnsignedIntParameter(pname);
2761  case GraphicsContext3D::STENCIL_BITS:
2762  if (!m_framebufferBinding && !m_attributes.stencil)
2763  return WebGLGetInfo(intZero);
2764  return getIntParameter(pname);
2765  case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2766  return getIntParameter(pname);
2767  case GraphicsContext3D::STENCIL_FAIL:
2768  return getUnsignedIntParameter(pname);
2769  case GraphicsContext3D::STENCIL_FUNC:
2770  return getUnsignedIntParameter(pname);
2771  case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2772  return getUnsignedIntParameter(pname);
2773  case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2774  return getUnsignedIntParameter(pname);
2775  case GraphicsContext3D::STENCIL_REF:
2776  return getIntParameter(pname);
2777  case GraphicsContext3D::STENCIL_TEST:
2778  return getBooleanParameter(pname);
2779  case GraphicsContext3D::STENCIL_VALUE_MASK:
2780  return getUnsignedIntParameter(pname);
2781  case GraphicsContext3D::STENCIL_WRITEMASK:
2782  return getUnsignedIntParameter(pname);
2783  case GraphicsContext3D::SUBPIXEL_BITS:
2784  return getIntParameter(pname);
2785  case GraphicsContext3D::TEXTURE_BINDING_2D:
2786  return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding));
2787  case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2788  return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding));
2789  case GraphicsContext3D::UNPACK_ALIGNMENT:
2790  return getIntParameter(pname);
2791  case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2792  return WebGLGetInfo(m_unpackFlipY);
2793  case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2794  return WebGLGetInfo(m_unpackPremultiplyAlpha);
2795  case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2796  return WebGLGetInfo(m_unpackColorspaceConversion);
2797  case GraphicsContext3D::VENDOR:
2798  return WebGLGetInfo(String("WebKit"));
2799  case GraphicsContext3D::VERSION:
2800  return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
2801  case GraphicsContext3D::VIEWPORT:
2802  return getWebGLIntArrayParameter(pname);
2803  case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2804  if (m_oesStandardDerivatives)
2805  return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2806  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
2807  return WebGLGetInfo();
2808  case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
2809  if (m_webglDebugRendererInfo)
2810  return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
2811  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2812  return WebGLGetInfo();
2813  case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
2814  if (m_webglDebugRendererInfo)
2815  return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
2816  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2817  return WebGLGetInfo();
2818  case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2819  if (m_oesVertexArrayObject) {
2820  if (!m_boundVertexArrayObject->isDefaultObject())
2821  return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
2822  return WebGLGetInfo();
2823  }
2824  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
2825  return WebGLGetInfo();
2826  case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
2827  if (m_extTextureFilterAnisotropic)
2828  return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
2829  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
2830  return WebGLGetInfo();
2831  case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
2832  if (m_webglDrawBuffers)
2833  return WebGLGetInfo(getMaxColorAttachments());
2834  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
2835  return WebGLGetInfo();
2836  case Extensions3D::MAX_DRAW_BUFFERS_EXT:
2837  if (m_webglDrawBuffers)
2838  return WebGLGetInfo(getMaxDrawBuffers());
2839  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
2840  return WebGLGetInfo();
2841  default:
2842  if (m_webglDrawBuffers
2843  && pname >= Extensions3D::DRAW_BUFFER0_EXT
2844  && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
2845  GC3Dint value = GraphicsContext3D::NONE;
2846  if (m_framebufferBinding)
2847  value = m_framebufferBinding->getDrawBuffer(pname);
2848  else // emulated backbuffer
2849  value = m_backDrawBuffer;
2850  return WebGLGetInfo(value);
2851  }
2852  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
2853  return WebGLGetInfo();
2854  }
2855 }
2856 
2857 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
2858 {
2859  UNUSED_PARAM(ec);
2860  if (isContextLostOrPending() || !validateWebGLObject("getProgramParameter", program))
2861  return WebGLGetInfo();
2862 
2863  GC3Dint value = 0;
2864  switch (pname) {
2865  case GraphicsContext3D::DELETE_STATUS:
2866  return WebGLGetInfo(program->isDeleted());
2867  case GraphicsContext3D::VALIDATE_STATUS:
2868  m_context->getProgramiv(objectOrZero(program), pname, &value);
2869  return WebGLGetInfo(static_cast<bool>(value));
2870  case GraphicsContext3D::LINK_STATUS:
2871  return WebGLGetInfo(program->getLinkStatus());
2872  case GraphicsContext3D::ATTACHED_SHADERS:
2873  m_context->getProgramiv(objectOrZero(program), pname, &value);
2874  return WebGLGetInfo(value);
2875  case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2876  case GraphicsContext3D::ACTIVE_UNIFORMS:
2877  m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), pname, &value);
2878  return WebGLGetInfo(value);
2879  default:
2880  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name");
2881  return WebGLGetInfo();
2882  }
2883 }
2884 
2885 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
2886 {
2887  UNUSED_PARAM(ec);
2888  if (isContextLostOrPending())
2889  return String();
2890  if (!validateWebGLObject("getProgramInfoLog", program))
2891  return "";
2892  return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
2893 }
2894 
2895 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2896 {
2897  UNUSED_PARAM(ec);
2898  if (isContextLostOrPending())
2899  return WebGLGetInfo();
2900  if (target != GraphicsContext3D::RENDERBUFFER) {
2901  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target");
2902  return WebGLGetInfo();
2903  }
2904  if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2905  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound");
2906  return WebGLGetInfo();
2907  }
2908 
2909  if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
2910  && !m_renderbufferBinding->isValid()) {
2911  ASSERT(!isDepthStencilSupported());
2912  int value = 0;
2913  switch (pname) {
2914  case GraphicsContext3D::RENDERBUFFER_WIDTH:
2915  value = m_renderbufferBinding->getWidth();
2916  break;
2917  case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2918  value = m_renderbufferBinding->getHeight();
2919  break;
2920  case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2921  case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2922  case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2923  case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2924  value = 0;
2925  break;
2926  case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2927  value = 24;
2928  break;
2929  case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2930  value = 8;
2931  break;
2932  case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2933  return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2934  default:
2935  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2936  return WebGLGetInfo();
2937  }
2938  return WebGLGetInfo(value);
2939  }
2940 
2941  GC3Dint value = 0;
2942  switch (pname) {
2943  case GraphicsContext3D::RENDERBUFFER_WIDTH:
2944  case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2945  case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2946  case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2947  case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2948  case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2949  case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2950  case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2951  m_context->getRenderbufferParameteriv(target, pname, &value);
2952  return WebGLGetInfo(value);
2953  case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2954  return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2955  default:
2956  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2957  return WebGLGetInfo();
2958  }
2959 }
2960 
2961 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
2962 {
2963  UNUSED_PARAM(ec);
2964  if (isContextLostOrPending() || !validateWebGLObject("getShaderParameter", shader))
2965  return WebGLGetInfo();
2966  GC3Dint value = 0;
2967  switch (pname) {
2968  case GraphicsContext3D::DELETE_STATUS:
2969  return WebGLGetInfo(shader->isDeleted());
2970  case GraphicsContext3D::COMPILE_STATUS:
2971  m_context->getShaderiv(objectOrZero(shader), pname, &value);
2972  return WebGLGetInfo(static_cast<bool>(value));
2973  case GraphicsContext3D::SHADER_TYPE:
2974  m_context->getShaderiv(objectOrZero(shader), pname, &value);
2975  return WebGLGetInfo(static_cast<unsigned int>(value));
2976  default:
2977  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
2978  return WebGLGetInfo();
2979  }
2980 }
2981 
2982 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
2983 {
2984  UNUSED_PARAM(ec);
2985  if (isContextLostOrPending())
2986  return String();
2987  if (!validateWebGLObject("getShaderInfoLog", shader))
2988  return "";
2989  return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
2990 }
2991 
2992 PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec)
2993 {
2994  UNUSED_PARAM(ec);
2995  if (isContextLostOrPending())
2996  return nullptr;
2997  switch (shaderType) {
2998  case GraphicsContext3D::VERTEX_SHADER:
2999  case GraphicsContext3D::FRAGMENT_SHADER:
3000  break;
3001  default:
3002  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type");
3003  return nullptr;
3004  }
3005  switch (precisionType) {
3006  case GraphicsContext3D::LOW_FLOAT:
3007  case GraphicsContext3D::MEDIUM_FLOAT:
3008  case GraphicsContext3D::HIGH_FLOAT:
3009  case GraphicsContext3D::LOW_INT:
3010  case GraphicsContext3D::MEDIUM_INT:
3011  case GraphicsContext3D::HIGH_INT:
3012  break;
3013  default:
3014  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type");
3015  return nullptr;
3016  }
3017 
3018  GC3Dint range[2] = {0, 0};
3019  GC3Dint precision = 0;
3020  m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision);
3021  return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
3022 }
3023 
3024 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
3025 {
3026  UNUSED_PARAM(ec);
3027  if (isContextLostOrPending())
3028  return String();
3029  if (!validateWebGLObject("getShaderSource", shader))
3030  return "";
3031  return ensureNotNull(shader->getSource());
3032 }
3033 
3034 Vector<String> WebGLRenderingContext::getSupportedExtensions()
3035 {
3036  Vector<String> result;
3037 
3038  if (m_isPendingPolicyResolution)
3039  return result;
3040 
3041  if (m_context->getExtensions()->supports("GL_OES_texture_float"))
3042  result.append("OES_texture_float");
3043  if (m_context->getExtensions()->supports("GL_OES_texture_float_linear"))
3044  result.append("OES_texture_float_linear");
3045  if (m_context->getExtensions()->supports("GL_OES_texture_half_float"))
3046  result.append("OES_texture_half_float");
3047  if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear"))
3048  result.append("OES_texture_half_float_linear");
3049  if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
3050  result.append("OES_standard_derivatives");
3051  if (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))
3052  result.append("EXT_shader_texture_lod");
3053  if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
3054  result.append("WEBKIT_EXT_texture_filter_anisotropic");
3055  if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
3056  result.append("OES_vertex_array_object");
3057  if (m_context->getExtensions()->supports("GL_OES_element_index_uint"))
3058  result.append("OES_element_index_uint");
3059  result.append("WEBGL_lose_context");
3060  if (WebGLCompressedTextureATC::supported(this))
3061  result.append("WEBKIT_WEBGL_compressed_texture_atc");
3062  if (WebGLCompressedTexturePVRTC::supported(this))
3063  result.append("WEBKIT_WEBGL_compressed_texture_pvrtc");
3064  if (WebGLCompressedTextureS3TC::supported(this))
3065  result.append("WEBGL_compressed_texture_s3tc");
3066  if (WebGLDepthTexture::supported(graphicsContext3D()))
3067  result.append("WEBGL_depth_texture");
3068  if (supportsDrawBuffers())
3069  result.append("WEBGL_draw_buffers");
3070  if (ANGLEInstancedArrays::supported(this))
3071  result.append("ANGLE_instanced_arrays");
3072 
3073  if (allowPrivilegedExtensions()) {
3074  if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
3075  result.append("WEBGL_debug_shaders");
3076  result.append("WEBGL_debug_renderer_info");
3077  }
3078 
3079  return result;
3080 }
3081 
3082 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
3083 {
3084  UNUSED_PARAM(ec);
3085  if (isContextLostOrPending())
3086  return WebGLGetInfo();
3087  WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false);
3088  if (!tex)
3089  return WebGLGetInfo();
3090  GC3Dint value = 0;
3091  switch (pname) {
3092  case GraphicsContext3D::TEXTURE_MAG_FILTER:
3093  case GraphicsContext3D::TEXTURE_MIN_FILTER:
3094  case GraphicsContext3D::TEXTURE_WRAP_S:
3095  case GraphicsContext3D::TEXTURE_WRAP_T:
3096  m_context->getTexParameteriv(target, pname, &value);
3097  return WebGLGetInfo(static_cast<unsigned int>(value));
3098  case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
3099  if (m_extTextureFilterAnisotropic) {
3100  m_context->getTexParameteriv(target, pname, &value);
3101  return WebGLGetInfo(static_cast<unsigned int>(value));
3102  }
3103  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
3104  return WebGLGetInfo();
3105  default:
3106  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name");
3107  return WebGLGetInfo();
3108  }
3109 }
3110 
3111 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
3112 {
3113  UNUSED_PARAM(ec);
3114  if (isContextLostOrPending() || !validateWebGLObject("getUniform", program))
3115  return WebGLGetInfo();
3116  if (!uniformLocation || uniformLocation->program() != program) {
3117  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program");
3118  return WebGLGetInfo();
3119  }
3120  GC3Dint location = uniformLocation->location();
3121 
3122  GC3Denum baseType;
3123  unsigned length;
3124  switch (uniformLocation->type()) {
3125  case GraphicsContext3D::BOOL:
3126  baseType = GraphicsContext3D::BOOL;
3127  length = 1;
3128  break;
3129  case GraphicsContext3D::BOOL_VEC2:
3130  baseType = GraphicsContext3D::BOOL;
3131  length = 2;
3132  break;
3133  case GraphicsContext3D::BOOL_VEC3:
3134  baseType = GraphicsContext3D::BOOL;
3135  length = 3;
3136  break;
3137  case GraphicsContext3D::BOOL_VEC4:
3138  baseType = GraphicsContext3D::BOOL;
3139  length = 4;
3140  break;
3141  case GraphicsContext3D::INT:
3142  baseType = GraphicsContext3D::INT;
3143  length = 1;
3144  break;
3145  case GraphicsContext3D::INT_VEC2:
3146  baseType = GraphicsContext3D::INT;
3147  length = 2;
3148  break;
3149  case GraphicsContext3D::INT_VEC3:
3150  baseType = GraphicsContext3D::INT;
3151  length = 3;
3152  break;
3153  case GraphicsContext3D::INT_VEC4:
3154  baseType = GraphicsContext3D::INT;
3155  length = 4;
3156  break;
3157  case GraphicsContext3D::FLOAT:
3158  baseType = GraphicsContext3D::FLOAT;
3159  length = 1;
3160  break;
3161  case GraphicsContext3D::FLOAT_VEC2:
3162  baseType = GraphicsContext3D::FLOAT;
3163  length = 2;
3164  break;
3165  case GraphicsContext3D::FLOAT_VEC3:
3166  baseType = GraphicsContext3D::FLOAT;
3167  length = 3;
3168  break;
3169  case GraphicsContext3D::FLOAT_VEC4:
3170  baseType = GraphicsContext3D::FLOAT;
3171  length = 4;
3172  break;
3173  case GraphicsContext3D::FLOAT_MAT2:
3174  baseType = GraphicsContext3D::FLOAT;
3175  length = 4;
3176  break;
3177  case GraphicsContext3D::FLOAT_MAT3:
3178  baseType = GraphicsContext3D::FLOAT;
3179  length = 9;
3180  break;
3181  case GraphicsContext3D::FLOAT_MAT4:
3182  baseType = GraphicsContext3D::FLOAT;
3183  length = 16;
3184  break;
3185  case GraphicsContext3D::SAMPLER_2D:
3186  case GraphicsContext3D::SAMPLER_CUBE:
3187  baseType = GraphicsContext3D::INT;
3188  length = 1;
3189  break;
3190  default:
3191  // Can't handle this type
3192  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type");
3193  return WebGLGetInfo();
3194  }
3195  switch (baseType) {
3196  case GraphicsContext3D::FLOAT: {
3197  GC3Dfloat value[16] = {0};
3198  if (m_isRobustnessEXTSupported)
3199  m_context->getExtensions()->getnUniformfvEXT(objectOrZero(program), location, 16 * sizeof(GC3Dfloat), value);
3200  else
3201  m_context->getUniformfv(objectOrZero(program), location, value);
3202  if (length == 1)
3203  return WebGLGetInfo(value[0]);
3204  return WebGLGetInfo(Float32Array::create(value, length));
3205  }
3206  case GraphicsContext3D::INT: {
3207  GC3Dint value[4] = {0};
3208  if (m_isRobustnessEXTSupported)
3209  m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
3210  else
3211  m_context->getUniformiv(objectOrZero(program), location, value);
3212  if (length == 1)
3213  return WebGLGetInfo(value[0]);
3214  return WebGLGetInfo(Int32Array::create(value, length));
3215  }
3216  case GraphicsContext3D::BOOL: {
3217  GC3Dint value[4] = {0};
3218  if (m_isRobustnessEXTSupported)
3219  m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
3220  else
3221  m_context->getUniformiv(objectOrZero(program), location, value);
3222  if (length > 1) {
3223  bool boolValue[16] = {0};
3224  for (unsigned j = 0; j < length; j++)
3225  boolValue[j] = static_cast<bool>(value[j]);
3226  return WebGLGetInfo(boolValue, length);
3227  }
3228  return WebGLGetInfo(static_cast<bool>(value[0]));
3229  }
3230  default:
3231  notImplemented();
3232  }
3233 
3234  // If we get here, something went wrong in our unfortunately complex logic above
3235  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error");
3236  return WebGLGetInfo();
3237 }
3238 
3239 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
3240 {
3241  UNUSED_PARAM(ec);
3242  if (isContextLostOrPending() || !validateWebGLObject("getUniformLocation", program))
3243  return nullptr;
3244  if (!validateLocationLength("getUniformLocation", name))
3245  return nullptr;
3246  if (!validateString("getUniformLocation", name))
3247  return nullptr;
3248  if (isPrefixReserved(name))
3249  return nullptr;
3250  if (!program->getLinkStatus()) {
3251  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked");
3252  return nullptr;
3253  }
3254  GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
3255  if (uniformLocation == -1)
3256  return nullptr;
3257 
3258  GC3Dint activeUniforms = 0;
3259  m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
3260  for (GC3Dint i = 0; i < activeUniforms; i++) {
3261  ActiveInfo info;
3262  if (!m_context->getActiveUniform(objectOrZero(program), i, info))
3263  return nullptr;
3264  // Strip "[0]" from the name if it's an array.
3265  if (info.name.endsWith("[0]"))
3266  info.name = info.name.left(info.name.length() - 3);
3267  // If it's an array, we need to iterate through each element, appending "[index]" to the name.
3268  for (GC3Dint index = 0; index < info.size; ++index) {
3269  String uniformName = info.name + "[" + String::number(index) + "]";
3270 
3271  if (name == uniformName || name == info.name)
3272  return WebGLUniformLocation::create(program, uniformLocation, info.type);
3273  }
3274  }
3275  return nullptr;
3276 }
3277 
3278 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
3279 {
3280  UNUSED_PARAM(ec);
3281 
3282  if (isContextLostOrPending())
3283  return WebGLGetInfo();
3284 
3285  if (index >= m_maxVertexAttribs) {
3286  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range");
3287  return WebGLGetInfo();
3288  }
3289 
3290  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
3291 
3292  if (m_angleInstancedArrays && pname == GraphicsContext3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE)
3293  return WebGLGetInfo(state.divisor);
3294 
3295  switch (pname) {
3296  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3297  if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
3298  || !state.bufferBinding
3299  || !state.bufferBinding->object())
3300  return WebGLGetInfo();
3301  return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
3302  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
3303  return WebGLGetInfo(state.enabled);
3304  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
3305  return WebGLGetInfo(state.normalized);
3306  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
3307  return WebGLGetInfo(state.size);
3308  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
3309  return WebGLGetInfo(state.originalStride);
3310  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
3311  return WebGLGetInfo(state.type);
3312  case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
3313  return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
3314  default:
3315  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name");
3316  return WebGLGetInfo();
3317  }
3318 }
3319 
3320 long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
3321 {
3322  if (isContextLostOrPending())
3323  return 0;
3324  GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
3325  return static_cast<long long>(result);
3326 }
3327 
3328 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
3329 {
3330  if (isContextLostOrPending())
3331  return;
3332  bool isValid = false;
3333  switch (target) {
3334  case GraphicsContext3D::GENERATE_MIPMAP_HINT:
3335  isValid = true;
3336  break;
3337  case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
3338  if (m_oesStandardDerivatives)
3339  isValid = true;
3340  break;
3341  }
3342  if (!isValid) {
3343  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
3344  return;
3345  }
3346  m_context->hint(target, mode);
3347 }
3348 
3349 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
3350 {
3351  if (!buffer || isContextLostOrPending())
3352  return 0;
3353 
3354  if (!buffer->hasEverBeenBound())
3355  return 0;
3356 
3357  return m_context->isBuffer(buffer->object());
3358 }
3359 
3360 bool WebGLRenderingContext::isContextLost() const
3361 {
3362  return m_contextLost;
3363 }
3364 
3365 bool WebGLRenderingContext::isContextLostOrPending()
3366 {
3367  if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) {
3368  LOG(WebGL, "Context is being used. Attempt to resolve the policy.");
3369  Document& document = canvas()->document().topDocument();
3370  Page* page = document.page();
3371  if (page && !document.url().isLocalFile())
3372  page->mainFrame().loader().client().resolveWebGLPolicyForURL(document.url());
3373  // FIXME: We don't currently do anything with the result from resolution. A more
3374  // complete implementation might try to construct a real context, etc and proceed
3375  // with normal operation.
3376  // https://bugs.webkit.org/show_bug.cgi?id=129122
3377  m_hasRequestedPolicyResolution = true;
3378  }
3379 
3380  return m_contextLost || m_isPendingPolicyResolution;
3381 }
3382 
3383 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
3384 {
3385  if (isContextLostOrPending() || !validateCapability("isEnabled", cap))
3386  return 0;
3387  if (cap == GraphicsContext3D::STENCIL_TEST)
3388  return m_stencilEnabled;
3389  return m_context->isEnabled(cap);
3390 }
3391 
3392 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
3393 {
3394  if (!framebuffer || isContextLostOrPending())
3395  return 0;
3396 
3397  if (!framebuffer->hasEverBeenBound())
3398  return 0;
3399 
3400  return m_context->isFramebuffer(framebuffer->object());
3401 }
3402 
3403 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
3404 {
3405  if (!program || isContextLostOrPending())
3406  return 0;
3407 
3408  return m_context->isProgram(program->object());
3409 }
3410 
3411 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
3412 {
3413  if (!renderbuffer || isContextLostOrPending())
3414  return 0;
3415 
3416  if (!renderbuffer->hasEverBeenBound())
3417  return 0;
3418 
3419  return m_context->isRenderbuffer(renderbuffer->object());
3420 }
3421 
3422 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
3423 {
3424  if (!shader || isContextLostOrPending())
3425  return 0;
3426 
3427  return m_context->isShader(shader->object());
3428 }
3429 
3430 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
3431 {
3432  if (!texture || isContextLostOrPending())
3433  return 0;
3434 
3435  if (!texture->hasEverBeenBound())
3436  return 0;
3437 
3438  return m_context->isTexture(texture->object());
3439 }
3440 
3441 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
3442 {
3443  if (isContextLostOrPending())
3444  return;
3445  m_context->lineWidth(width);
3446 }
3447 
3448 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
3449 {
3450  UNUSED_PARAM(ec);
3451  if (isContextLostOrPending() || !validateWebGLObject("linkProgram", program))
3452  return;
3453  if (!isGLES2Compliant()) {
3454  WebGLShader* vertexShader = program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER);
3455  WebGLShader* fragmentShader = program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER);
3456  if (!vertexShader || !vertexShader->isValid() || !fragmentShader || !fragmentShader->isValid() || !m_context->precisionsMatch(objectOrZero(vertexShader), objectOrZero(fragmentShader)) || !m_context->checkVaryingsPacking(objectOrZero(vertexShader), objectOrZero(fragmentShader))) {
3457  program->setLinkStatus(false);
3458  return;
3459  }
3460  }
3461 
3462  m_context->linkProgram(objectOrZero(program));
3463  program->increaseLinkCount();
3464 }
3465 
3466 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
3467 {
3468  if (isContextLostOrPending())
3469  return;
3470  switch (pname) {
3471  case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
3472  m_unpackFlipY = param;
3473  break;
3474  case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
3475  m_unpackPremultiplyAlpha = param;
3476  break;
3477  case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
3478  if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
3479  m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
3480  else {
3481  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
3482  return;
3483  }
3484  break;
3485  case GraphicsContext3D::PACK_ALIGNMENT:
3486  case GraphicsContext3D::UNPACK_ALIGNMENT:
3487  if (param == 1 || param == 2 || param == 4 || param == 8) {
3488  if (pname == GraphicsContext3D::PACK_ALIGNMENT)
3489  m_packAlignment = param;
3490  else // GraphicsContext3D::UNPACK_ALIGNMENT:
3491  m_unpackAlignment = param;
3492  m_context->pixelStorei(pname, param);
3493  } else {
3494  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment");
3495  return;
3496  }
3497  break;
3498  default:
3499  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name");
3500  return;
3501  }
3502 }
3503 
3504 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
3505 {
3506  if (isContextLostOrPending())
3507  return;
3508  m_context->polygonOffset(factor, units);
3509 }
3510 
3511 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
3512 {
3513  if (isContextLostOrPending())
3514  return;
3515  // Due to WebGL's same-origin restrictions, it is not possible to
3516  // taint the origin using the WebGL API.
3517  ASSERT(canvas()->originClean());
3518  // Validate input parameters.
3519  if (!pixels) {
3520  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView");
3521  return;
3522  }
3523  switch (format) {
3524  case GraphicsContext3D::ALPHA:
3525  case GraphicsContext3D::RGB:
3526  case GraphicsContext3D::RGBA:
3527  break;
3528  default:
3529  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
3530  return;
3531  }
3532  switch (type) {
3533  case GraphicsContext3D::UNSIGNED_BYTE:
3534  case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3535  case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3536  case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3537  break;
3538  default:
3539  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
3540  return;
3541  }
3542  if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
3543  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
3544  return;
3545  }
3546  // Validate array type against pixel type.
3547  if (pixels->getType() != JSC::TypeUint8) {
3548  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
3549  return;
3550  }
3551  const char* reason = "framebuffer incomplete";
3552  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
3553  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
3554  return;
3555  }
3556  // Calculate array size, taking into consideration of PACK_ALIGNMENT.
3557  unsigned int totalBytesRequired = 0;
3558  unsigned int padding = 0;
3559  if (!m_isRobustnessEXTSupported) {
3560  GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
3561  if (error != GraphicsContext3D::NO_ERROR) {
3562  synthesizeGLError(error, "readPixels", "invalid dimensions");
3563  return;
3564  }
3565  if (pixels->byteLength() < totalBytesRequired) {
3566  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
3567  return;
3568  }
3569  }
3570 
3571  clearIfComposited();
3572  void* data = pixels->baseAddress();
3573 
3574  {
3575  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
3576  if (m_isRobustnessEXTSupported)
3577  m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels->byteLength(), data);
3578  else
3579  m_context->readPixels(x, y, width, height, format, type, data);
3580  }
3581 
3582 #if OS(DARWIN)
3583  if (m_isRobustnessEXTSupported) // we haven't computed padding
3584  m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
3585  // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
3586  // on QC is fixed, i.e., when alpha is off, readPixels should
3587  // set alpha to 255 instead of 0.
3588  if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
3589  unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
3590  for (GC3Dsizei iy = 0; iy < height; ++iy) {
3591  for (GC3Dsizei ix = 0; ix < width; ++ix) {
3592  pixels[3] = 255;
3593  pixels += 4;
3594  }
3595  pixels += padding;
3596  }
3597  }
3598 #endif
3599 }
3600 
3601 void WebGLRenderingContext::releaseShaderCompiler()
3602 {
3603  if (isContextLostOrPending())
3604  return;
3605  m_context->releaseShaderCompiler();
3606 }
3607 
3608 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
3609 {
3610  if (isContextLostOrPending())
3611  return;
3612  if (target != GraphicsContext3D::RENDERBUFFER) {
3613  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
3614  return;
3615  }
3616  if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
3617  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
3618  return;
3619  }
3620  if (!validateSize("renderbufferStorage", width, height))
3621  return;
3622  switch (internalformat) {
3623  case GraphicsContext3D::DEPTH_COMPONENT16:
3624  case GraphicsContext3D::RGBA4:
3625  case GraphicsContext3D::RGB5_A1:
3626  case GraphicsContext3D::RGB565:
3627  case GraphicsContext3D::STENCIL_INDEX8:
3628  m_context->renderbufferStorage(target, internalformat, width, height);
3629  m_renderbufferBinding->setInternalFormat(internalformat);
3630  m_renderbufferBinding->setIsValid(true);
3631  m_renderbufferBinding->setSize(width, height);
3632  break;
3633  case GraphicsContext3D::DEPTH_STENCIL:
3634  if (isDepthStencilSupported()) {
3635  m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
3636  }
3637  m_renderbufferBinding->setSize(width, height);
3638  m_renderbufferBinding->setIsValid(isDepthStencilSupported());
3639  m_renderbufferBinding->setInternalFormat(internalformat);
3640  break;
3641  default:
3642  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
3643  return;
3644  }
3645  applyStencilTest();
3646 }
3647 
3648 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
3649 {
3650  if (isContextLostOrPending())
3651  return;
3652  m_context->sampleCoverage(value, invert);
3653 }
3654 
3655 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
3656 {
3657  if (isContextLostOrPending())
3658  return;
3659  if (!validateSize("scissor", width, height))
3660  return;
3661  m_context->scissor(x, y, width, height);
3662 }
3663 
3664 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
3665 {
3666  UNUSED_PARAM(ec);
3667  if (isContextLostOrPending() || !validateWebGLObject("shaderSource", shader))
3668  return;
3669  String stringWithoutComments = StripComments(string).result();
3670  if (!validateString("shaderSource", stringWithoutComments))
3671  return;
3672  shader->setSource(string);
3673  m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
3674 }
3675 
3676 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
3677 {
3678  if (isContextLostOrPending())
3679  return;
3680  if (!validateStencilFunc("stencilFunc", func))
3681  return;
3682  m_stencilFuncRef = ref;
3683  m_stencilFuncRefBack = ref;
3684  m_stencilFuncMask = mask;
3685  m_stencilFuncMaskBack = mask;
3686  m_context->stencilFunc(func, ref, mask);
3687 }
3688 
3689 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
3690 {
3691  if (isContextLostOrPending())
3692  return;
3693  if (!validateStencilFunc("stencilFuncSeparate", func))
3694  return;
3695  switch (face) {
3696  case GraphicsContext3D::FRONT_AND_BACK:
3697  m_stencilFuncRef = ref;
3698  m_stencilFuncRefBack = ref;
3699  m_stencilFuncMask = mask;
3700  m_stencilFuncMaskBack = mask;
3701  break;
3702  case GraphicsContext3D::FRONT:
3703  m_stencilFuncRef = ref;
3704  m_stencilFuncMask = mask;
3705  break;
3706  case GraphicsContext3D::BACK:
3707  m_stencilFuncRefBack = ref;
3708  m_stencilFuncMaskBack = mask;
3709  break;
3710  default:
3711  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face");
3712  return;
3713  }
3714  m_context->stencilFuncSeparate(face, func, ref, mask);
3715 }
3716 
3717 void WebGLRenderingContext::stencilMask(GC3Duint mask)
3718 {
3719  if (isContextLostOrPending())
3720  return;
3721  m_stencilMask = mask;
3722  m_stencilMaskBack = mask;
3723  m_context->stencilMask(mask);
3724 }
3725 
3726 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3727 {
3728  if (isContextLostOrPending())
3729  return;
3730  switch (face) {
3731  case GraphicsContext3D::FRONT_AND_BACK:
3732  m_stencilMask = mask;
3733  m_stencilMaskBack = mask;
3734  break;
3735  case GraphicsContext3D::FRONT:
3736  m_stencilMask = mask;
3737  break;
3738  case GraphicsContext3D::BACK:
3739  m_stencilMaskBack = mask;
3740  break;
3741  default:
3742  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face");
3743  return;
3744  }
3745  m_context->stencilMaskSeparate(face, mask);
3746 }
3747 
3748 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3749 {
3750  if (isContextLostOrPending())
3751  return;
3752  m_context->stencilOp(fail, zfail, zpass);
3753 }
3754 
3755 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3756 {
3757  if (isContextLostOrPending())
3758  return;
3759  m_context->stencilOpSeparate(face, fail, zfail, zpass);
3760 }
3761 
3762 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
3763 {
3764  // FIXME: For now we ignore any errors returned.
3765  ec = 0;
3766  WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
3767  ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type));
3768  ASSERT(tex);
3769  ASSERT(!level || !WebGLTexture::isNPOT(width, height));
3770  if (!pixels) {
3771  // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true.
3772  // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures
3773  // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
3774  // clear.
3775  if (isResourceSafe())
3776  m_context->texImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
3777  else {
3778  bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
3779  border, format, type, m_unpackAlignment);
3780  if (!succeed)
3781  return;
3782  }
3783  } else {
3784  ASSERT(validateSettableTexFormat("texImage2D", internalformat));
3785  m_context->moveErrorsToSyntheticErrorList();
3786  m_context->texImage2D(target, level, internalformat, width, height,
3787  border, format, type, pixels);
3788  if (m_context->moveErrorsToSyntheticErrorList()) {
3789  // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
3790  tex->markInvalid(target, level);
3791  return;
3792  }
3793  }
3794  tex->setLevelInfo(target, level, internalformat, width, height, type);
3795 }
3796 
3797 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3798 {
3799  ec = 0;
3800  Vector<uint8_t> data;
3801  GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
3802  if (!imageExtractor.extractSucceeded()) {
3803  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3804  return;
3805  }
3806  GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
3807  GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
3808  const void* imagePixelData = imageExtractor.imagePixelData();
3809 
3810  bool needConversion = true;
3811  if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
3812  needConversion = false;
3813  else {
3814  if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
3815  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error");
3816  return;
3817  }
3818  }
3819 
3820  if (m_unpackAlignment != 1)
3821  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3822  texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, ec);
3823  if (m_unpackAlignment != 1)
3824  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3825 }
3826 
3827 bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset)
3828 {
3829  if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type))
3830  return false;
3831 
3832  WebGLTexture* texture = validateTextureBinding(functionName, target, true);
3833  if (!texture)
3834  return false;
3835 
3836  if (functionType == NotTexSubImage2D) {
3837  if (level && WebGLTexture::isNPOT(width, height)) {
3838  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2");
3839  return false;
3840  }
3841  // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
3842  // by checking if the ArrayBufferView is null or not.
3843  if (sourceType != SourceArrayBufferView) {
3844  if (!validateSettableTexFormat(functionName, format))
3845  return false;
3846  }
3847  } else {
3848  if (!validateSettableTexFormat(functionName, format))
3849  return false;
3850  if (!validateSize(functionName, xoffset, yoffset))
3851  return false;
3852  // Before checking if it is in the range, check if overflow happens first.
3853  if (xoffset + width < 0 || yoffset + height < 0) {
3854  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "bad dimensions");
3855  return false;
3856  }
3857  if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) {
3858  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
3859  return false;
3860  }
3861  if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) {
3862  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
3863  return false;
3864  }
3865  }
3866 
3867  return true;
3868 }
3869 
3870 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3871  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3872  GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3873 {
3874  if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed)
3875  || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
3876  return;
3877  void* data = pixels ? pixels->baseAddress() : 0;
3878  Vector<uint8_t> tempData;
3879  bool changeUnpackAlignment = false;
3880  if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3881  if (!m_context->extractTextureData(width, height, format, type,
3882  m_unpackAlignment,
3883  m_unpackFlipY, m_unpackPremultiplyAlpha,
3884  data,
3885  tempData))
3886  return;
3887  data = tempData.data();
3888  changeUnpackAlignment = true;
3889  }
3890  if (changeUnpackAlignment)
3891  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3892  texImage2DBase(target, level, internalformat, width, height, border,
3893  format, type, data, ec);
3894  if (changeUnpackAlignment)
3895  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3896 }
3897 
3898 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3899  GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3900 {
3901  ec = 0;
3902  if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
3903  return;
3904  Vector<uint8_t> data;
3905  bool needConversion = true;
3906  // The data from ImageData is always of format RGBA8.
3907  // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
3908  if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
3909  needConversion = false;
3910  else {
3911  if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3912  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3913  return;
3914  }
3915  }
3916  if (m_unpackAlignment != 1)
3917  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3918  texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
3919  if (m_unpackAlignment != 1)
3920  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3921 }
3922 
3923 PassRefPtr<Image> WebGLRenderingContext::drawImageIntoBuffer(Image* image, int width, int height, int deviceScaleFactor)
3924 {
3925  IntSize size(width, height);
3926  size.scale(deviceScaleFactor);
3927  ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
3928  if (!buf) {
3929  synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
3930  return nullptr;
3931  }
3932 
3933  FloatRect srcRect(FloatPoint(), image->size());
3934  FloatRect destRect(FloatPoint(), size);
3935  buf->context()->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect);
3936  return buf->copyImage(ImageBuffer::fastCopyImageMode());
3937 }
3938 
3939 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3940  GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3941 {
3942  ec = 0;
3943  if (isContextLostOrPending() || !validateHTMLImageElement("texImage2D", image, ec))
3944  return;
3945 
3946  RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
3947  if (imageForRender->isSVGImage())
3948  imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
3949 
3950  if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
3951  return;
3952 
3953  texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3954 }
3955 
3956 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3957  GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3958 {
3959  ec = 0;
3960  if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
3961  return;
3962 
3963  WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
3964  // If possible, copy from the canvas element directly to the texture
3965  // via the GPU, without a read-back to system memory.
3966  //
3967  // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when
3968  // ImageBuffer::copyToPlatformTexture implementations are fully functional.
3969  if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level)
3970  && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) && type == GraphicsContext3D::UNSIGNED_BYTE) {
3971  ImageBuffer* buffer = canvas->buffer();
3972  if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
3973  texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
3974  return;
3975  }
3976  }
3977 
3978  RefPtr<ImageData> imageData = canvas->getImageData();
3979  if (imageData)
3980  texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
3981  else
3982  texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3983 }
3984 
3985 #if ENABLE(VIDEO)
3986 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy, ExceptionCode&)
3987 {
3988  IntSize size(video->videoWidth(), video->videoHeight());
3989  ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
3990  if (!buf) {
3991  synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
3992  return nullptr;
3993  }
3994  IntRect destRect(0, 0, size.width(), size.height());
3995  // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
3996  video->paintCurrentFrameInContext(buf->context(), destRect);
3997  return buf->copyImage(backingStoreCopy);
3998 }
3999 
4000 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
4001  GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
4002 {
4003  ec = 0;
4004  if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video, ec)
4005  || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
4006  return;
4007 
4008  // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
4009  // Otherwise, it will fall back to the normal SW path.
4010  // FIXME: The current restrictions require that format shoud be RGB or RGBA,
4011  // type should be UNSIGNED_BYTE and level should be 0. It may be lifted in the future.
4012  WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
4013  if (GraphicsContext3D::TEXTURE_2D == target && texture
4014  && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
4015  && type == GraphicsContext3D::UNSIGNED_BYTE
4016  && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level))
4017  && !level) {
4018  if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
4019  texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
4020  return;
4021  }
4022  }
4023 
4024  // Normal pure SW path.
4025  RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
4026  if (!image)
4027  return;
4028  texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4029 }
4030 #endif
4031 
4032 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
4033 {
4034  if (isContextLostOrPending())
4035  return;
4036  WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
4037  if (!tex)
4038  return;
4039  switch (pname) {
4040  case GraphicsContext3D::TEXTURE_MIN_FILTER:
4041  case GraphicsContext3D::TEXTURE_MAG_FILTER:
4042  break;
4043  case GraphicsContext3D::TEXTURE_WRAP_S:
4044  case GraphicsContext3D::TEXTURE_WRAP_T:
4045  if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
4046  || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
4047  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter");
4048  return;
4049  }
4050  break;
4051  case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
4052  if (!m_extTextureFilterAnisotropic) {
4053  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled");
4054  return;
4055  }
4056  break;
4057  default:
4058  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name");
4059  return;
4060  }
4061  if (isFloat) {
4062  tex->setParameterf(pname, paramf);
4063  m_context->texParameterf(target, pname, paramf);
4064  } else {
4065  tex->setParameteri(pname, parami);
4066  m_context->texParameteri(target, pname, parami);
4067  }
4068 }
4069 
4070 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
4071 {
4072  texParameter(target, pname, param, 0, true);
4073 }
4074 
4075 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
4076 {
4077  texParameter(target, pname, 0, param, false);
4078 }
4079 
4080 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
4081 {
4082  // FIXME: For now we ignore any errors returned
4083  ec = 0;
4084  ASSERT(!isContextLost());
4085  ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type));
4086  ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
4087  ASSERT(validateSettableTexFormat("texSubImage2D", format));
4088  WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
4089  if (!tex) {
4090  ASSERT_NOT_REACHED();
4091  return;
4092  }
4093  ASSERT((xoffset + width) >= 0);
4094  ASSERT((yoffset + height) >= 0);
4095  ASSERT(tex->getWidth(target, level) >= (xoffset + width));
4096  ASSERT(tex->getHeight(target, level) >= (yoffset + height));
4097  ASSERT(tex->getInternalFormat(target, level) == format);
4098  ASSERT(tex->getType(target, level) == type);
4099  m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
4100 }
4101 
4102 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
4103 {
4104  ec = 0;
4105  Vector<uint8_t> data;
4106  GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
4107  if (!imageExtractor.extractSucceeded()) {
4108  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
4109  return;
4110  }
4111  GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
4112  GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
4113  const void* imagePixelData = imageExtractor.imagePixelData();
4114 
4115  bool needConversion = true;
4116  if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
4117  needConversion = false;
4118  else {
4119  if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
4120  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
4121  return;
4122  }
4123  }
4124 
4125  if (m_unpackAlignment != 1)
4126  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
4127  texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, ec);
4128  if (m_unpackAlignment != 1)
4129  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
4130 }
4131 
4132 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4133  GC3Dsizei width, GC3Dsizei height,
4134  GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
4135 {
4136  if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed)
4137  || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
4138  return;
4139  void* data = pixels->baseAddress();
4140  Vector<uint8_t> tempData;
4141  bool changeUnpackAlignment = false;
4142  if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
4143  if (!m_context->extractTextureData(width, height, format, type,
4144  m_unpackAlignment,
4145  m_unpackFlipY, m_unpackPremultiplyAlpha,
4146  data,
4147  tempData))
4148  return;
4149  data = tempData.data();
4150  changeUnpackAlignment = true;
4151  }
4152  if (changeUnpackAlignment)
4153  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
4154  texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
4155  if (changeUnpackAlignment)
4156  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
4157 }
4158 
4159 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4160  GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
4161 {
4162  ec = 0;
4163  if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
4164  return;
4165 
4166  Vector<uint8_t> data;
4167  bool needConversion = true;
4168  // The data from ImageData is always of format RGBA8.
4169  // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
4170  if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
4171  needConversion = false;
4172  else {
4173  if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
4174  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
4175  return;
4176  }
4177  }
4178  if (m_unpackAlignment != 1)
4179  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
4180  texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
4181  if (m_unpackAlignment != 1)
4182  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
4183 }
4184 
4185 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4186  GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
4187 {
4188  ec = 0;
4189  if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
4190  return;
4191 
4192  RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
4193  if (imageForRender->isSVGImage())
4194  imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
4195 
4196  if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
4197  return;
4198 
4199  texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4200 }
4201 
4202 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4203  GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
4204 {
4205  ec = 0;
4206  if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
4207  || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
4208  return;
4209 
4210  RefPtr<ImageData> imageData = canvas->getImageData();
4211  if (imageData)
4212  texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
4213  else
4214  texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4215 }
4216 
4217 #if ENABLE(VIDEO)
4218 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4219  GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
4220 {
4221  ec = 0;
4222  if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
4223  || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
4224  return;
4225 
4226  RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
4227  if (!image)
4228  return;
4229  texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4230 }
4231 #endif
4232 
4233 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
4234 {
4235  UNUSED_PARAM(ec);
4236  if (isContextLostOrPending() || !location)
4237  return;
4238 
4239  if (location->program() != m_currentProgram) {
4240  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program");
4241  return;
4242  }
4243 
4244  m_context->uniform1f(location->location(), x);
4245 }
4246 
4247 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4248 {
4249  UNUSED_PARAM(ec);
4250  if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, 1))
4251  return;
4252 
4253  m_context->uniform1fv(location->location(), v->length(), v->data());
4254 }
4255 
4256 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4257 {
4258  UNUSED_PARAM(ec);
4259  if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, size, 1))
4260  return;
4261 
4262  m_context->uniform1fv(location->location(), size, v);
4263 }
4264 
4265 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
4266 {
4267  UNUSED_PARAM(ec);
4268  if (isContextLostOrPending() || !location)
4269  return;
4270 
4271  if (location->program() != m_currentProgram) {
4272  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program");
4273  return;
4274  }
4275 
4276  if ((location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) && x >= (int)m_textureUnits.size()) {
4277  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1i", "invalid texture unit");
4278  return;
4279  }
4280 
4281  m_context->uniform1i(location->location(), x);
4282 }
4283 
4284 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4285 {
4286  UNUSED_PARAM(ec);
4287  if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, 1))
4288  return;
4289 
4290  if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE)
4291  for (unsigned i = 0; i < v->length(); ++i) {
4292  if (v->data()[i] >= static_cast<int>(m_textureUnits.size())) {
4293  LOG(WebGL, "Texture unit size=%zu, v[%d]=%d. Location type = %04X.", m_textureUnits.size(), i, v->data()[i], location->type());
4294  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
4295  return;
4296  }
4297  }
4298 
4299  m_context->uniform1iv(location->location(), v->length(), v->data());
4300 }
4301 
4302 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4303 {
4304  UNUSED_PARAM(ec);
4305  if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, size, 1))
4306  return;
4307 
4308  if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE)
4309  for (unsigned i = 0; i < static_cast<unsigned>(size); ++i) {
4310  if (((GC3Dint*)v)[i] >= static_cast<int>(m_textureUnits.size())) {
4311  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
4312  return;
4313  }
4314  }
4315 
4316  m_context->uniform1iv(location->location(), size, v);
4317 }
4318 
4319 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
4320 {
4321  UNUSED_PARAM(ec);
4322  if (isContextLostOrPending() || !location)
4323  return;
4324 
4325  if (location->program() != m_currentProgram) {
4326  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program");
4327  return;
4328  }
4329 
4330  m_context->uniform2f(location->location(), x, y);
4331 }
4332 
4333 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4334 {
4335  UNUSED_PARAM(ec);
4336  if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, 2))
4337  return;
4338 
4339  m_context->uniform2fv(location->location(), v->length() / 2, v->data());
4340 }
4341 
4342 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4343 {
4344  UNUSED_PARAM(ec);
4345  if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, size, 2))
4346  return;
4347 
4348  m_context->uniform2fv(location->location(), size / 2, v);
4349 }
4350 
4351 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
4352 {
4353  UNUSED_PARAM(ec);
4354  if (isContextLostOrPending() || !location)
4355  return;
4356 
4357  if (location->program() != m_currentProgram) {
4358  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program");
4359  return;
4360  }
4361 
4362  m_context->uniform2i(location->location(), x, y);
4363 }
4364 
4365 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4366 {
4367  UNUSED_PARAM(ec);
4368  if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, 2))
4369  return;
4370 
4371  m_context->uniform2iv(location->location(), v->length() / 2, v->data());
4372 }
4373 
4374 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4375 {
4376  UNUSED_PARAM(ec);
4377  if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, size, 2))
4378  return;
4379 
4380  m_context->uniform2iv(location->location(), size / 2, v);
4381 }
4382 
4383 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
4384 {
4385  UNUSED_PARAM(ec);
4386  if (isContextLostOrPending() || !location)
4387  return;
4388 
4389  if (location->program() != m_currentProgram) {
4390  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program");
4391  return;
4392  }
4393 
4394  m_context->uniform3f(location->location(), x, y, z);
4395 }
4396 
4397 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4398 {
4399  UNUSED_PARAM(ec);
4400  if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, 3))
4401  return;
4402 
4403  m_context->uniform3fv(location->location(), v->length() / 3, v->data());
4404 }
4405 
4406 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4407 {
4408  UNUSED_PARAM(ec);
4409  if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, size, 3))
4410  return;
4411 
4412  m_context->uniform3fv(location->location(), size / 3, v);
4413 }
4414 
4415 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
4416 {
4417  UNUSED_PARAM(ec);
4418  if (isContextLostOrPending() || !location)
4419  return;
4420 
4421  if (location->program() != m_currentProgram) {
4422  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program");
4423  return;
4424  }
4425 
4426  m_context->uniform3i(location->location(), x, y, z);
4427 }
4428 
4429 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4430 {
4431  UNUSED_PARAM(ec);
4432  if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, 3))
4433  return;
4434 
4435  m_context->uniform3iv(location->location(), v->length() / 3, v->data());
4436 }
4437 
4438 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4439 {
4440  UNUSED_PARAM(ec);
4441  if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, size, 3))
4442  return;
4443 
4444  m_context->uniform3iv(location->location(), size / 3, v);
4445 }
4446 
4447 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
4448 {
4449  UNUSED_PARAM(ec);
4450  if (isContextLostOrPending() || !location)
4451  return;
4452 
4453  if (location->program() != m_currentProgram) {
4454  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program");
4455  return;
4456  }
4457 
4458  m_context->uniform4f(location->location(), x, y, z, w);
4459 }
4460 
4461 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4462 {
4463  UNUSED_PARAM(ec);
4464  if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, 4))
4465  return;
4466 
4467  m_context->uniform4fv(location->location(), v->length() / 4, v->data());
4468 }
4469 
4470 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4471 {
4472  UNUSED_PARAM(ec);
4473  if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, size, 4))
4474  return;
4475 
4476  m_context->uniform4fv(location->location(), size / 4, v);
4477 }
4478 
4479 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
4480 {
4481  UNUSED_PARAM(ec);
4482  if (isContextLostOrPending() || !location)
4483  return;
4484 
4485  if (location->program() != m_currentProgram) {
4486  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program");
4487  return;
4488  }
4489 
4490  m_context->uniform4i(location->location(), x, y, z, w);
4491 }
4492 
4493 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4494 {
4495  UNUSED_PARAM(ec);
4496  if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, 4))
4497  return;
4498 
4499  m_context->uniform4iv(location->location(), v->length() / 4, v->data());
4500 }
4501 
4502 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4503 {
4504  UNUSED_PARAM(ec);
4505  if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, size, 4))
4506  return;
4507 
4508  m_context->uniform4iv(location->location(), size / 4, v);
4509 }
4510 
4511 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4512 {
4513  UNUSED_PARAM(ec);
4514  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
4515  return;
4516  m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data());
4517 }
4518 
4519 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4520 {
4521  UNUSED_PARAM(ec);
4522  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
4523  return;
4524  m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
4525 }
4526 
4527 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4528 {
4529  UNUSED_PARAM(ec);
4530  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
4531  return;
4532  m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data());
4533 }
4534 
4535 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4536 {
4537  UNUSED_PARAM(ec);
4538  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
4539  return;
4540  m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
4541 }
4542 
4543 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4544 {
4545  UNUSED_PARAM(ec);
4546  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
4547  return;
4548  m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data());
4549 }
4550 
4551 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4552 {
4553  UNUSED_PARAM(ec);
4554  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
4555  return;
4556  m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
4557 }
4558 
4559 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
4560 {
4561  UNUSED_PARAM(ec);
4562  bool deleted;
4563  if (!checkObjectToBeBound("useProgram", program, deleted))
4564  return;
4565  if (deleted)
4566  program = 0;
4567  if (program && !program->getLinkStatus()) {
4568  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid");
4569  return;
4570  }
4571  if (m_currentProgram != program) {
4572  if (m_currentProgram)
4573  m_currentProgram->onDetached(graphicsContext3D());
4574  m_currentProgram = program;
4575  m_context->useProgram(objectOrZero(program));
4576  if (program)
4577  program->onAttached();
4578  }
4579 }
4580 
4581 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
4582 {
4583  UNUSED_PARAM(ec);
4584  if (isContextLostOrPending() || !validateWebGLObject("validateProgram", program))
4585  return;
4586  m_context->validateProgram(objectOrZero(program));
4587 }
4588 
4589 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
4590 {
4591  vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
4592 }
4593 
4594 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
4595 {
4596  vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
4597 }
4598 
4599 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4600 {
4601  vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
4602 }
4603 
4604 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
4605 {
4606  vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
4607 }
4608 
4609 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
4610 {
4611  vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
4612 }
4613 
4614 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4615 {
4616  vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
4617 }
4618 
4619 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
4620 {
4621  vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
4622 }
4623 
4624 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
4625 {
4626  vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
4627 }
4628 
4629 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4630 {
4631  vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
4632 }
4633 
4634 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
4635 {
4636  vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
4637 }
4638 
4639 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
4640 {
4641  vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
4642 }
4643 
4644 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4645 {
4646  vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
4647 }
4648 
4649 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
4650 {
4651  UNUSED_PARAM(ec);
4652  if (isContextLostOrPending())
4653  return;
4654  switch (type) {
4655  case GraphicsContext3D::BYTE:
4656  case GraphicsContext3D::UNSIGNED_BYTE:
4657  case GraphicsContext3D::SHORT:
4658  case GraphicsContext3D::UNSIGNED_SHORT:
4659  case GraphicsContext3D::FLOAT:
4660  break;
4661  default:
4662  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4663  return;
4664  }
4665  if (index >= m_maxVertexAttribs) {
4666  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range");
4667  return;
4668  }
4669  if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
4670  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset");
4671  return;
4672  }
4673  if (!m_boundArrayBuffer) {
4674  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER");
4675  return;
4676  }
4677  // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
4678  unsigned int typeSize = sizeInBytes(type);
4679  if (!typeSize) {
4680  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4681  return;
4682  }
4683  if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
4684  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type");
4685  return;
4686  }
4687  GC3Dsizei bytesPerElement = size * typeSize;
4688 
4689  m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer);
4690  m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
4691 }
4692 
4693 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
4694 {
4695  if (isContextLostOrPending())
4696  return;
4697  if (!validateSize("viewport", width, height))
4698  return;
4699  m_context->viewport(x, y, width, height);
4700 }
4701 
4702 void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
4703 {
4704  if (isContextLostOrPending()) {
4705  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost");
4706  return;
4707  }
4708 
4709  m_contextGroup->loseContextGroup(mode);
4710 }
4711 
4712 void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode)
4713 {
4714  if (isContextLost())
4715  return;
4716 
4717  m_contextLost = true;
4718  m_contextLostMode = mode;
4719 
4720  if (mode == RealLostContext) {
4721  // Inform the embedder that a lost context was received. In response, the embedder might
4722  // decide to take action such as asking the user for permission to use WebGL again.
4723  if (Frame* frame = canvas()->document().frame())
4724  frame->loader().client().didLoseWebGLContext(m_context->getExtensions()->getGraphicsResetStatusARB());
4725  }
4726 
4727  detachAndRemoveAllObjects();
4728 
4729  if (m_drawingBuffer) {
4730  // Make absolutely sure we do not refer to an already-deleted texture or framebuffer.
4731  m_drawingBuffer->setTexture2DBinding(0);
4732  m_drawingBuffer->setFramebufferBinding(0);
4733  }
4734 
4735  // There is no direct way to clear errors from a GL implementation and
4736  // looping until getError() becomes NO_ERROR might cause an infinite loop if
4737  // the driver or context implementation had a bug. So, loop a reasonably
4738  // large number of times to clear any existing errors.
4739  for (int i = 0; i < 100; ++i) {
4740  if (m_context->getError() == GraphicsContext3D::NO_ERROR)
4741  break;
4742  }
4743  ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole;
4744  synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost", display);
4745 
4746  // Don't allow restoration unless the context lost event has both been
4747  // dispatched and its default behavior prevented.
4748  m_restoreAllowed = false;
4749 
4750  // Always defer the dispatch of the context lost event, to implement
4751  // the spec behavior of queueing a task.
4752  m_dispatchContextLostEventTimer.startOneShot(0);
4753 }
4754 
4755 void WebGLRenderingContext::forceRestoreContext()
4756 {
4757  if (!isContextLostOrPending()) {
4758  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost");
4759  return;
4760  }
4761 
4762  if (!m_restoreAllowed) {
4763  if (m_contextLostMode == SyntheticLostContext)
4764  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed");
4765  return;
4766  }
4767 
4768  if (!m_restoreTimer.isActive())
4769  m_restoreTimer.startOneShot(0);
4770 }
4771 
4772 PlatformLayer* WebGLRenderingContext::platformLayer() const
4773 {
4774  return (!isContextLost() && !m_isPendingPolicyResolution) ? m_context->platformLayer() : 0;
4775 }
4776 
4777 void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
4778 {
4779  if (m_isPendingPolicyResolution)
4780  return;
4781 
4782  m_contextGroup->removeObject(object);
4783 }
4784 
4785 void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object)
4786 {
4787  if (m_isPendingPolicyResolution)
4788  return;
4789 
4790  ASSERT(!isContextLost());
4791  m_contextGroup->addObject(object);
4792 }
4793 
4794 void WebGLRenderingContext::removeContextObject(WebGLContextObject* object)
4795 {
4796  if (m_isPendingPolicyResolution)
4797  return;
4798 
4799  m_contextObjects.remove(object);
4800 }
4801 
4802 void WebGLRenderingContext::addContextObject(WebGLContextObject* object)
4803 {
4804  if (m_isPendingPolicyResolution)
4805  return;
4806 
4807  ASSERT(!isContextLost());
4808  m_contextObjects.add(object);
4809 }
4810 
4811 void WebGLRenderingContext::detachAndRemoveAllObjects()
4812 {
4813  if (m_isPendingPolicyResolution)
4814  return;
4815 
4816  while (m_contextObjects.size() > 0) {
4817  HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
4818  (*it)->detachContext();
4819  }
4820 }
4821 
4822 bool WebGLRenderingContext::hasPendingActivity() const
4823 {
4824  return false;
4825 }
4826 
4827 void WebGLRenderingContext::stop()
4828 {
4829  if (!isContextLost() && !m_isPendingPolicyResolution) {
4830  forceLostContext(SyntheticLostContext);
4831  destroyGraphicsContext3D();
4832  }
4833 }
4834 
4835 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
4836 {
4837  GC3Dboolean value = 0;
4838  m_context->getBooleanv(pname, &value);
4839  return WebGLGetInfo(static_cast<bool>(value));
4840 }
4841 
4842 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
4843 {
4844  if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
4845  notImplemented();
4846  return WebGLGetInfo(0, 0);
4847  }
4848  GC3Dboolean value[4] = {0};
4849  m_context->getBooleanv(pname, value);
4850  bool boolValue[4];
4851  for (int ii = 0; ii < 4; ++ii)
4852  boolValue[ii] = static_cast<bool>(value[ii]);
4853  return WebGLGetInfo(boolValue, 4);
4854 }
4855 
4856 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
4857 {
4858  GC3Dfloat value = 0;
4859  m_context->getFloatv(pname, &value);
4860  return WebGLGetInfo(value);
4861 }
4862 
4863 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
4864 {
4865  GC3Dint value = 0;
4866  m_context->getIntegerv(pname, &value);
4867  return WebGLGetInfo(value);
4868 }
4869 
4870 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
4871 {
4872  GC3Dint value = 0;
4873  m_context->getIntegerv(pname, &value);
4874  return WebGLGetInfo(static_cast<unsigned int>(value));
4875 }
4876 
4877 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
4878 {
4879  GC3Dfloat value[4] = {0};
4880  m_context->getFloatv(pname, value);
4881  unsigned length = 0;
4882  switch (pname) {
4883  case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4884  case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4885  case GraphicsContext3D::DEPTH_RANGE:
4886  length = 2;
4887  break;
4888  case GraphicsContext3D::BLEND_COLOR:
4889  case GraphicsContext3D::COLOR_CLEAR_VALUE:
4890  length = 4;
4891  break;
4892  default:
4893  notImplemented();
4894  }
4895  return WebGLGetInfo(Float32Array::create(value, length));
4896 }
4897 
4898 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4899 {
4900  GC3Dint value[4] = {0};
4901  m_context->getIntegerv(pname, value);
4902  unsigned length = 0;
4903  switch (pname) {
4904  case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4905  length = 2;
4906  break;
4907  case GraphicsContext3D::SCISSOR_BOX:
4908  case GraphicsContext3D::VIEWPORT:
4909  length = 4;
4910  break;
4911  default:
4912  notImplemented();
4913  }
4914  return WebGLGetInfo(Int32Array::create(value, length));
4915 }
4916 
4917 void WebGLRenderingContext::checkTextureCompleteness(const char* functionName, bool prepareToDraw)
4918 {
4919  bool resetActiveUnit = false;
4920  WebGLTexture::TextureExtensionFlag extensions = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0));
4921 
4922  for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
4923  if ((m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
4924  || (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))) {
4925  if (ii != m_activeTextureUnit) {
4926  m_context->activeTexture(ii);
4927  resetActiveUnit = true;
4928  } else if (resetActiveUnit) {
4929  m_context->activeTexture(ii);
4930  resetActiveUnit = false;
4931  }
4932  WebGLTexture* tex2D;
4933  WebGLTexture* texCubeMap;
4934  if (prepareToDraw) {
4935  String msg(String("texture bound to texture unit ") + String::number(ii)
4936  + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete',"
4937  + " or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled.");
4938  printGLWarningToConsole(functionName, msg.utf8().data());
4939  tex2D = m_blackTexture2D.get();
4940  texCubeMap = m_blackTextureCubeMap.get();
4941  } else {
4942  tex2D = m_textureUnits[ii].texture2DBinding.get();
4943  texCubeMap = m_textureUnits[ii].textureCubeMapBinding.get();
4944  }
4945  if (m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
4946  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
4947  if (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))
4948  m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
4949  }
4950  }
4951  if (resetActiveUnit)
4952  m_context->activeTexture(m_activeTextureUnit);
4953 }
4954 
4955 void WebGLRenderingContext::createFallbackBlackTextures1x1()
4956 {
4957  unsigned char black[] = {0, 0, 0, 255};
4958  m_blackTexture2D = createTexture();
4959  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
4960  m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
4961  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4962  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
4963  m_blackTextureCubeMap = createTexture();
4964  m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
4965  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4966  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4967  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4968  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4969  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4970  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4971  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4972  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4973  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4974  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4975  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4976  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4977  m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
4978 }
4979 
4980 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
4981  GC3Denum colorBufferFormat)
4982 {
4983  unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
4984  unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
4985  return (need & have) == need;
4986 }
4987 
4988 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
4989 {
4990  if (m_framebufferBinding && m_framebufferBinding->object())
4991  return m_framebufferBinding->getColorBufferFormat();
4992  if (m_attributes.alpha)
4993  return GraphicsContext3D::RGBA;
4994  return GraphicsContext3D::RGB;
4995 }
4996 
4997 int WebGLRenderingContext::getBoundFramebufferWidth()
4998 {
4999  if (m_framebufferBinding && m_framebufferBinding->object())
5000  return m_framebufferBinding->getColorBufferWidth();
5001  return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width();
5002 }
5003 
5004 int WebGLRenderingContext::getBoundFramebufferHeight()
5005 {
5006  if (m_framebufferBinding && m_framebufferBinding->object())
5007  return m_framebufferBinding->getColorBufferHeight();
5008  return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height();
5009 }
5010 
5011 WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap)
5012 {
5013  WebGLTexture* texture = nullptr;
5014  switch (target) {
5015  case GraphicsContext3D::TEXTURE_2D:
5016  texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get();
5017  break;
5018  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
5019  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
5020  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
5021  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
5022  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
5023  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
5024  if (!useSixEnumsForCubeMap) {
5025  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
5026  return nullptr;
5027  }
5028  texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
5029  break;
5030  case GraphicsContext3D::TEXTURE_CUBE_MAP:
5031  if (useSixEnumsForCubeMap) {
5032  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
5033  return nullptr;
5034  }
5035  texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
5036  break;
5037  default:
5038  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
5039  return nullptr;
5040  }
5041  if (!texture)
5042  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture");
5043  return texture;
5044 }
5045 
5046 bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string)
5047 {
5048  const unsigned maxWebGLLocationLength = 256;
5049  if (string.length() > maxWebGLLocationLength) {
5050  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256");
5051  return false;
5052  }
5053  return true;
5054 }
5055 
5056 bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y)
5057 {
5058  if (x < 0 || y < 0) {
5059  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
5060  return false;
5061  }
5062  return true;
5063 }
5064 
5065 bool WebGLRenderingContext::validateString(const char* functionName, const String& string)
5066 {
5067  for (size_t i = 0; i < string.length(); ++i) {
5068  if (!validateCharacter(string[i])) {
5069  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII");
5070  return false;
5071  }
5072  }
5073  return true;
5074 }
5075 
5076 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
5077 {
5078  switch (format) {
5079  case GraphicsContext3D::ALPHA:
5080  case GraphicsContext3D::LUMINANCE:
5081  case GraphicsContext3D::LUMINANCE_ALPHA:
5082  case GraphicsContext3D::RGB:
5083  case GraphicsContext3D::RGBA:
5084  break;
5085  case GraphicsContext3D::DEPTH_STENCIL:
5086  case GraphicsContext3D::DEPTH_COMPONENT:
5087  if (m_webglDepthTexture)
5088  break;
5089  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
5090  return false;
5091  default:
5092  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
5093  return false;
5094  }
5095 
5096  switch (type) {
5097  case GraphicsContext3D::UNSIGNED_BYTE:
5098  case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
5099  case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
5100  case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
5101  break;
5102  case GraphicsContext3D::FLOAT:
5103  if (m_oesTextureFloat)
5104  break;
5105  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5106  return false;
5107  case GraphicsContext3D::HALF_FLOAT_OES:
5108  if (m_oesTextureHalfFloat)
5109  break;
5110  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5111  return false;
5112  case GraphicsContext3D::UNSIGNED_INT:
5113  case GraphicsContext3D::UNSIGNED_INT_24_8:
5114  case GraphicsContext3D::UNSIGNED_SHORT:
5115  if (m_webglDepthTexture)
5116  break;
5117  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5118  return false;
5119  default:
5120  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5121  return false;
5122  }
5123 
5124  // Verify that the combination of format and type is supported.
5125  switch (format) {
5126  case GraphicsContext3D::ALPHA:
5127  case GraphicsContext3D::LUMINANCE:
5128  case GraphicsContext3D::LUMINANCE_ALPHA:
5129  if (type != GraphicsContext3D::UNSIGNED_BYTE
5130  && type != GraphicsContext3D::FLOAT
5131  && type != GraphicsContext3D::HALF_FLOAT_OES) {
5132  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
5133  return false;
5134  }
5135  break;
5136  case GraphicsContext3D::RGB:
5137  if (type != GraphicsContext3D::UNSIGNED_BYTE
5138  && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
5139  && type != GraphicsContext3D::FLOAT
5140  && type != GraphicsContext3D::HALF_FLOAT_OES) {
5141  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
5142  return false;
5143  }
5144  break;
5145  case GraphicsContext3D::RGBA:
5146  if (type != GraphicsContext3D::UNSIGNED_BYTE
5147  && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
5148  && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
5149  && type != GraphicsContext3D::FLOAT
5150  && type != GraphicsContext3D::HALF_FLOAT_OES) {
5151  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
5152  return false;
5153  }
5154  break;
5155  case GraphicsContext3D::DEPTH_COMPONENT:
5156  if (!m_webglDepthTexture) {
5157  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
5158  return false;
5159  }
5160  if (type != GraphicsContext3D::UNSIGNED_SHORT
5161  && type != GraphicsContext3D::UNSIGNED_INT) {
5162  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
5163  return false;
5164  }
5165  if (level > 0) {
5166  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
5167  return false;
5168  }
5169  break;
5170  case GraphicsContext3D::DEPTH_STENCIL:
5171  if (!m_webglDepthTexture) {
5172  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
5173  return false;
5174  }
5175  if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
5176  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
5177  return false;
5178  }
5179  if (level > 0) {
5180  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
5181  return false;
5182  }
5183  break;
5184  default:
5185  ASSERT_NOT_REACHED();
5186  }
5187 
5188  return true;
5189 }
5190 
5191 bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
5192 {
5193  if (level < 0) {
5194  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
5195  return false;
5196  }
5197  switch (target) {
5198  case GraphicsContext3D::TEXTURE_2D:
5199  if (level >= m_maxTextureLevel) {
5200  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
5201  return false;
5202  }
5203  break;
5204  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
5205  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
5206  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
5207  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
5208  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
5209  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
5210  if (level >= m_maxCubeMapTextureLevel) {
5211  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
5212  return false;
5213  }
5214  break;
5215  }
5216  // This function only checks if level is legal, so we return true and don't
5217  // generate INVALID_ENUM if target is illegal.
5218  return true;
5219 }
5220 
5221 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
5222  TexFuncValidationFunctionType functionType,
5223  GC3Denum target, GC3Dint level,
5224  GC3Denum internalformat,
5225  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
5226  GC3Denum format, GC3Denum type)
5227 {
5228  // We absolutely have to validate the format and type combination.
5229  // The texImage2D entry points taking HTMLImage, etc. will produce
5230  // temporary data based on this combination, so it must be legal.
5231  if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
5232  return false;
5233 
5234  if (width < 0 || height < 0) {
5235  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
5236  return false;
5237  }
5238 
5239  GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
5240  switch (target) {
5241  case GraphicsContext3D::TEXTURE_2D:
5242  if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
5243  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
5244  return false;
5245  }
5246  break;
5247  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
5248  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
5249  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
5250  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
5251  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
5252  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
5253  if (functionType != TexSubImage2D && width != height) {
5254  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
5255  return false;
5256  }
5257  // No need to check height here. For texImage width == height.
5258  // For texSubImage that will be checked when checking yoffset + height is in range.
5259  if (width > maxTextureSizeForLevel) {
5260  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
5261  return false;
5262  }
5263  break;
5264  default:
5265  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5266  return false;
5267  }
5268 
5269  if (format != internalformat) {
5270  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
5271  return false;
5272  }
5273 
5274  if (border) {
5275  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
5276  return false;
5277  }
5278 
5279  return true;
5280 }
5281 
5282 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
5283  GC3Dsizei width, GC3Dsizei height,
5284  GC3Denum format, GC3Denum type,
5285  ArrayBufferView* pixels,
5286  NullDisposition disposition)
5287 {
5288  if (!pixels) {
5289  if (disposition == NullAllowed)
5290  return true;
5291  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
5292  return false;
5293  }
5294 
5295  if (!validateTexFuncFormatAndType(functionName, format, type, level))
5296  return false;
5297  if (!validateSettableTexFormat(functionName, format))
5298  return false;
5299 
5300  switch (type) {
5301  case GraphicsContext3D::UNSIGNED_BYTE:
5302  if (pixels->getType() != JSC::TypeUint8) {
5303  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
5304  return false;
5305  }
5306  break;
5307  case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
5308  case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
5309  case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
5310  if (pixels->getType() != JSC::TypeUint16) {
5311  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
5312  return false;
5313  }
5314  break;
5315  case GraphicsContext3D::FLOAT: // OES_texture_float
5316  if (pixels->getType() != JSC::TypeFloat32) {
5317  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
5318  return false;
5319  }
5320  break;
5321  case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
5322  // As per the specification, ArrayBufferView should be null when
5323  // OES_texture_half_float is enabled.
5324  if (pixels) {
5325  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
5326  return false;
5327  }
5328  break;
5329  default:
5330  ASSERT_NOT_REACHED();
5331  }
5332 
5333  unsigned int totalBytesRequired;
5334  GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
5335  if (error != GraphicsContext3D::NO_ERROR) {
5336  synthesizeGLError(error, functionName, "invalid texture dimensions");
5337  return false;
5338  }
5339  if (pixels->byteLength() < totalBytesRequired) {
5340  if (m_unpackAlignment != 1) {
5341  error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
5342  if (pixels->byteLength() == totalBytesRequired) {
5343  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
5344  return false;
5345  }
5346  }
5347  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
5348  return false;
5349  }
5350  return true;
5351 }
5352 
5353 bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format)
5354 {
5355  return m_compressedTextureFormats.contains(format);
5356 }
5357 
5358 bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName,
5359  GC3Dsizei width, GC3Dsizei height,
5360  GC3Denum format, ArrayBufferView* pixels)
5361 {
5362  if (!pixels) {
5363  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
5364  return false;
5365  }
5366  if (width < 0 || height < 0) {
5367  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
5368  return false;
5369  }
5370 
5371  unsigned int bytesRequired = 0;
5372 
5373  switch (format) {
5374  case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5375  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5376  case Extensions3D::COMPRESSED_ATC_RGB_AMD:
5377  {
5378  const int kBlockSize = 8;
5379  const int kBlockWidth = 4;
5380  const int kBlockHeight = 4;
5381  int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5382  int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5383  bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
5384  }
5385  break;
5386  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5387  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
5388  case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD:
5389  case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
5390  {
5391  const int kBlockSize = 16;
5392  const int kBlockWidth = 4;
5393  const int kBlockHeight = 4;
5394  int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5395  int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5396  bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
5397  }
5398  break;
5399  case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
5400  case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
5401  {
5402  const int kBlockSize = 8;
5403  const int kBlockWidth = 8;
5404  const int kBlockHeight = 8;
5405  bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 4 + 7) / kBlockSize;
5406  }
5407  break;
5408  case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
5409  case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
5410  {
5411  const int kBlockSize = 8;
5412  const int kBlockWidth = 16;
5413  const int kBlockHeight = 8;
5414  bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 2 + 7) / kBlockSize;
5415  }
5416  break;
5417  default:
5418  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format");
5419  return false;
5420  }
5421 
5422  if (pixels->byteLength() != bytesRequired) {
5423  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions");
5424  return false;
5425  }
5426 
5427  return true;
5428 }
5429 
5430 bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format)
5431 {
5432  switch (format) {
5433  case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5434  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5435  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5436  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5437  const GC3Dsizei kBlockWidth = 4;
5438  const GC3Dsizei kBlockHeight = 4;
5439  const GC3Dint maxTextureSize = target ? m_maxTextureSize : m_maxCubeMapTextureSize;
5440  const GC3Dsizei maxCompressedDimension = maxTextureSize >> level;
5441  bool widthValid = (level && width == 1) || (level && width == 2) || (!(width % kBlockWidth) && width <= maxCompressedDimension);
5442  bool heightValid = (level && height == 1) || (level && height == 2) || (!(height % kBlockHeight) && height <= maxCompressedDimension);
5443  if (!widthValid || !heightValid) {
5444  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
5445  return false;
5446  }
5447  return true;
5448  }
5449  case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
5450  case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
5451  case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
5452  case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
5453  // Height and width must be powers of 2.
5454  if ((width & (width - 1)) || (height & (height - 1))) {
5455  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
5456  return false;
5457  }
5458  return true;
5459  default:
5460  return false;
5461  }
5462 }
5463 
5464 bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
5465  GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
5466 {
5467  if (xoffset < 0 || yoffset < 0) {
5468  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
5469  return false;
5470  }
5471 
5472  switch (format) {
5473  case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5474  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5475  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5476  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5477  const int kBlockWidth = 4;
5478  const int kBlockHeight = 4;
5479  if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
5480  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4");
5481  return false;
5482  }
5483  if (width - xoffset > tex->getWidth(target, level)
5484  || height - yoffset > tex->getHeight(target, level)) {
5485  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range");
5486  return false;
5487  }
5488  return validateCompressedTexDimensions(functionName, target, level, width, height, format);
5489  }
5490  case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
5491  case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
5492  case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
5493  case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
5494  if (xoffset || yoffset) {
5495  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset and yoffset must be zero");
5496  return false;
5497  }
5498  if (width != tex->getWidth(target, level)
5499  || height != tex->getHeight(target, level)) {
5500  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions must match existing level");
5501  return false;
5502  }
5503  return validateCompressedTexDimensions(functionName, target, level, width, height, format);
5504  }
5505  default:
5506  return false;
5507  }
5508 }
5509 
5510 bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode)
5511 {
5512  switch (mode) {
5513  case GraphicsContext3D::POINTS:
5514  case GraphicsContext3D::LINE_STRIP:
5515  case GraphicsContext3D::LINE_LOOP:
5516  case GraphicsContext3D::LINES:
5517  case GraphicsContext3D::TRIANGLE_STRIP:
5518  case GraphicsContext3D::TRIANGLE_FAN:
5519  case GraphicsContext3D::TRIANGLES:
5520  return true;
5521  default:
5522  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode");
5523  return false;
5524  }
5525 }
5526 
5527 bool WebGLRenderingContext::validateStencilSettings(const char* functionName)
5528 {
5529  if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
5530  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match");
5531  return false;
5532  }
5533  return true;
5534 }
5535 
5536 bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Denum func)
5537 {
5538  switch (func) {
5539  case GraphicsContext3D::NEVER:
5540  case GraphicsContext3D::LESS:
5541  case GraphicsContext3D::LEQUAL:
5542  case GraphicsContext3D::GREATER:
5543  case GraphicsContext3D::GEQUAL:
5544  case GraphicsContext3D::EQUAL:
5545  case GraphicsContext3D::NOTEQUAL:
5546  case GraphicsContext3D::ALWAYS:
5547  return true;
5548  default:
5549  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function");
5550  return false;
5551  }
5552 }
5553 
5554 void WebGLRenderingContext::printGLErrorToConsole(const String& message)
5555 {
5556  if (!m_numGLErrorsToConsoleAllowed)
5557  return;
5558 
5559  --m_numGLErrorsToConsoleAllowed;
5560  printWarningToConsole(message);
5561 
5562  if (!m_numGLErrorsToConsoleAllowed)
5563  printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context.");
5564 }
5565 
5566 void WebGLRenderingContext::printWarningToConsole(const String& message)
5567 {
5568  if (!canvas())
5569  return;
5570  canvas()->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Warning, message);
5571 }
5572 
5573 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
5574 {
5575  if (target != GraphicsContext3D::FRAMEBUFFER) {
5576  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5577  return false;
5578  }
5579  switch (attachment) {
5580  case GraphicsContext3D::COLOR_ATTACHMENT0:
5581  case GraphicsContext3D::DEPTH_ATTACHMENT:
5582  case GraphicsContext3D::STENCIL_ATTACHMENT:
5583  case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
5584  break;
5585  default:
5586  if (m_webglDrawBuffers
5587  && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
5588  && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
5589  break;
5590  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
5591  return false;
5592  }
5593  return true;
5594 }
5595 
5596 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
5597 {
5598  switch (mode) {
5599  case GraphicsContext3D::FUNC_ADD:
5600  case GraphicsContext3D::FUNC_SUBTRACT:
5601  case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
5602  return true;
5603  default:
5604  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
5605  return false;
5606  }
5607 }
5608 
5609 bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst)
5610 {
5611  if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5612  && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
5613  || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5614  && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
5615  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst");
5616  return false;
5617  }
5618  return true;
5619 }
5620 
5621 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
5622 {
5623  switch (cap) {
5624  case GraphicsContext3D::BLEND:
5625  case GraphicsContext3D::CULL_FACE:
5626  case GraphicsContext3D::DEPTH_TEST:
5627  case GraphicsContext3D::DITHER:
5628  case GraphicsContext3D::POLYGON_OFFSET_FILL:
5629  case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
5630  case GraphicsContext3D::SAMPLE_COVERAGE:
5631  case GraphicsContext3D::SCISSOR_TEST:
5632  case GraphicsContext3D::STENCIL_TEST:
5633  return true;
5634  default:
5635  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
5636  return false;
5637  }
5638 }
5639 
5640 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
5641 {
5642  if (!v) {
5643  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5644  return false;
5645  }
5646  return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5647 }
5648 
5649 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
5650 {
5651  if (!v) {
5652  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5653  return false;
5654  }
5655  return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5656 }
5657 
5658 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5659 {
5660  return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize);
5661 }
5662 
5663 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
5664 {
5665  if (!v) {
5666  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5667  return false;
5668  }
5669  return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize);
5670 }
5671 
5672 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5673 {
5674  if (!location)
5675  return false;
5676  if (location->program() != m_currentProgram) {
5677  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program");
5678  return false;
5679  }
5680  if (!v) {
5681  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5682  return false;
5683  }
5684  if (transpose) {
5685  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE");
5686  return false;
5687  }
5688  if (size < requiredMinSize || (size % requiredMinSize)) {
5689  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5690  return false;
5691  }
5692  return true;
5693 }
5694 
5695 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage)
5696 {
5697  WebGLBuffer* buffer = 0;
5698  switch (target) {
5699  case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
5700  buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
5701  break;
5702  case GraphicsContext3D::ARRAY_BUFFER:
5703  buffer = m_boundArrayBuffer.get();
5704  break;
5705  default:
5706  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5707  return nullptr;
5708  }
5709  if (!buffer) {
5710  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer");
5711  return nullptr;
5712  }
5713  switch (usage) {
5714  case GraphicsContext3D::STREAM_DRAW:
5715  case GraphicsContext3D::STATIC_DRAW:
5716  case GraphicsContext3D::DYNAMIC_DRAW:
5717  return buffer;
5718  }
5719  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage");
5720  return nullptr;
5721 }
5722 
5723 bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionCode& ec)
5724 {
5725  if (!image || !image->cachedImage()) {
5726  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image");
5727  return false;
5728  }
5729  const URL& url = image->cachedImage()->response().url();
5730  if (url.isNull() || url.isEmpty() || !url.isValid()) {
5731  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image");
5732  return false;
5733  }
5734  if (wouldTaintOrigin(image)) {
5735  ec = SECURITY_ERR;
5736  return false;
5737  }
5738  return true;
5739 }
5740 
5741 bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionCode& ec)
5742 {
5743  if (!canvas || !canvas->buffer()) {
5744  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no canvas");
5745  return false;
5746  }
5747  if (wouldTaintOrigin(canvas)) {
5748  ec = SECURITY_ERR;
5749  return false;
5750  }
5751  return true;
5752 }
5753 
5754 #if ENABLE(VIDEO)
5755 bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionCode& ec)
5756 {
5757  if (!video || !video->videoWidth() || !video->videoHeight()) {
5758  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no video");
5759  return false;
5760  }
5761  if (wouldTaintOrigin(video)) {
5762  ec = SECURITY_ERR;
5763  return false;
5764  }
5765  return true;
5766 }
5767 #endif
5768 
5769 void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
5770 {
5771  if (isContextLostOrPending())
5772  return;
5773  if (index >= m_maxVertexAttribs) {
5774  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5775  return;
5776  }
5777  // In GL, we skip setting vertexAttrib0 values.
5778  if (index || isGLES2Compliant()) {
5779  switch (expectedSize) {
5780  case 1:
5781  m_context->vertexAttrib1f(index, v0);
5782  break;
5783  case 2:
5784  m_context->vertexAttrib2f(index, v0, v1);
5785  break;
5786  case 3:
5787  m_context->vertexAttrib3f(index, v0, v1, v2);
5788  break;
5789  case 4:
5790  m_context->vertexAttrib4f(index, v0, v1, v2, v3);
5791  break;
5792  }
5793  }
5794  VertexAttribValue& attribValue = m_vertexAttribValue[index];
5795  attribValue.value[0] = v0;
5796  attribValue.value[1] = v1;
5797  attribValue.value[2] = v2;
5798  attribValue.value[3] = v3;
5799 }
5800 
5801 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
5802 {
5803  if (isContextLostOrPending())
5804  return;
5805  if (!v) {
5806  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5807  return;
5808  }
5809  vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize);
5810 }
5811 
5812 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
5813 {
5814  if (isContextLostOrPending())
5815  return;
5816  if (!v) {
5817  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5818  return;
5819  }
5820  if (size < expectedSize) {
5821  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5822  return;
5823  }
5824  if (index >= m_maxVertexAttribs) {
5825  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5826  return;
5827  }
5828  // In GL, we skip setting vertexAttrib0 values.
5829  if (index || isGLES2Compliant()) {
5830  switch (expectedSize) {
5831  case 1:
5832  m_context->vertexAttrib1fv(index, v);
5833  break;
5834  case 2:
5835  m_context->vertexAttrib2fv(index, v);
5836  break;
5837  case 3:
5838  m_context->vertexAttrib3fv(index, v);
5839  break;
5840  case 4:
5841  m_context->vertexAttrib4fv(index, v);
5842  break;
5843  }
5844  }
5845  VertexAttribValue& attribValue = m_vertexAttribValue[index];
5846  attribValue.initValue();
5847  for (int ii = 0; ii < expectedSize; ++ii)
5848  attribValue.value[ii] = v[ii];
5849 }
5850 
5851 void WebGLRenderingContext::initVertexAttrib0()
5852 {
5853  WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5854 
5855  m_vertexAttrib0Buffer = createBuffer();
5856  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5857  m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
5858  m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
5859  state.bufferBinding = m_vertexAttrib0Buffer;
5860  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
5861  m_context->enableVertexAttribArray(0);
5862  m_vertexAttrib0BufferSize = 0;
5863  m_vertexAttrib0BufferValue[0] = 0.0f;
5864  m_vertexAttrib0BufferValue[1] = 0.0f;
5865  m_vertexAttrib0BufferValue[2] = 0.0f;
5866  m_vertexAttrib0BufferValue[3] = 1.0f;
5867  m_forceAttrib0BufferRefill = false;
5868  m_vertexAttrib0UsedBefore = false;
5869 }
5870 
5871 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
5872 {
5873  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5874  const VertexAttribValue& attribValue = m_vertexAttribValue[0];
5875  if (!m_currentProgram)
5876  return false;
5877  bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
5878  if (usingVertexAttrib0)
5879  m_vertexAttrib0UsedBefore = true;
5880  if (state.enabled && usingVertexAttrib0)
5881  return false;
5882  if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
5883  return false;
5884  m_vertexAttrib0UsedBefore = true;
5885  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5886  GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
5887  if (bufferDataSize > m_vertexAttrib0BufferSize) {
5888  m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
5889  m_vertexAttrib0BufferSize = bufferDataSize;
5890  m_forceAttrib0BufferRefill = true;
5891  }
5892  if (usingVertexAttrib0
5893  && (m_forceAttrib0BufferRefill
5894  || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
5895  || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
5896  || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
5897  || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
5898  auto bufferData = std::make_unique<GC3Dfloat[]>((numVertex + 1) * 4);
5899  for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
5900  bufferData[ii * 4] = attribValue.value[0];
5901  bufferData[ii * 4 + 1] = attribValue.value[1];
5902  bufferData[ii * 4 + 2] = attribValue.value[2];
5903  bufferData[ii * 4 + 3] = attribValue.value[3];
5904  }
5905  m_vertexAttrib0BufferValue[0] = attribValue.value[0];
5906  m_vertexAttrib0BufferValue[1] = attribValue.value[1];
5907  m_vertexAttrib0BufferValue[2] = attribValue.value[2];
5908  m_vertexAttrib0BufferValue[3] = attribValue.value[3];
5909  m_forceAttrib0BufferRefill = false;
5910  m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
5911  }
5912  m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
5913  return true;
5914 }
5915 
5916 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
5917 {
5918  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5919  if (state.bufferBinding != m_vertexAttrib0Buffer) {
5920  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
5921  m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
5922  }
5923  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
5924 }
5925 
5926 void WebGLRenderingContext::dispatchContextLostEvent()
5927 {
5928  RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
5929  canvas()->dispatchEvent(event);
5930  m_restoreAllowed = event->defaultPrevented();
5931  if (m_contextLostMode == RealLostContext && m_restoreAllowed)
5932  m_restoreTimer.startOneShot(0);
5933 }
5934 
5935 void WebGLRenderingContext::maybeRestoreContext()
5936 {
5937  ASSERT(m_contextLost);
5938  if (!m_contextLost)
5939  return;
5940 
5941  // The rendering context is not restored unless the default behavior of the
5942  // webglcontextlost event was prevented earlier.
5943  //
5944  // Because of the way m_restoreTimer is set up for real vs. synthetic lost
5945  // context events, we don't have to worry about this test short-circuiting
5946  // the retry loop for real context lost events.
5947  if (!m_restoreAllowed)
5948  return;
5949 
5950  int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
5951 
5952  switch (contextLostReason) {
5953  case GraphicsContext3D::NO_ERROR:
5954  // The GraphicsContext3D implementation might not fully
5955  // support GL_ARB_robustness semantics yet. Alternatively, the
5956  // WEBGL_lose_context extension might have been used to force
5957  // a lost context.
5958  break;
5959  case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
5960  // The rendering context is not restored if this context was
5961  // guilty of causing the graphics reset.
5962  printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
5963  return;
5964  case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
5965  // Always allow the context to be restored.
5966  break;
5967  case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
5968  // Warn. Ideally, prompt the user telling them that WebGL
5969  // content on the page might have caused the graphics card to
5970  // reset and ask them whether they want to continue running
5971  // the content. Only if they say "yes" should we start
5972  // attempting to restore the context.
5973  printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
5974  break;
5975  }
5976 
5977  Frame* frame = canvas()->document().frame();
5978  if (!frame)
5979  return;
5980 
5981  if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled()))
5982  return;
5983 
5984  FrameView* view = frame->view();
5985  if (!view)
5986  return;
5987  ScrollView* root = view->root();
5988  if (!root)
5989  return;
5990  HostWindow* hostWindow = root->hostWindow();
5991  if (!hostWindow)
5992  return;
5993 
5994  RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, hostWindow));
5995  if (!context) {
5996  if (m_contextLostMode == RealLostContext)
5997  m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
5998  else
5999  // This likely shouldn't happen but is the best way to report it to the WebGL app.
6000  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context");
6001  return;
6002  }
6003 
6004  // Construct a new drawing buffer with the new GraphicsContext3D.
6005  if (m_drawingBuffer) {
6006  m_drawingBuffer->discardResources();
6007  DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
6008  DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
6009  m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha);
6010  m_drawingBuffer->bind();
6011  }
6012 
6013  m_context = context;
6014  m_contextLost = false;
6015  setupFlags();
6016  initializeNewContext();
6017  canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
6018 }
6019 
6020 String WebGLRenderingContext::ensureNotNull(const String& text) const
6021 {
6022  if (text.isNull())
6023  return WTF::emptyString();
6024  return text;
6025 }
6026 
6027 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
6028  : m_buffers(std::make_unique<std::unique_ptr<ImageBuffer>[]>(capacity))
6029  , m_capacity(capacity)
6030 {
6031 }
6032 
6033 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
6034 {
6035  int i;
6036  for (i = 0; i < m_capacity; ++i) {
6037  ImageBuffer* buf = m_buffers[i].get();
6038  if (!buf)
6039  break;
6040  if (buf->logicalSize() != size)
6041  continue;
6042  bubbleToFront(i);
6043  return buf;
6044  }
6045 
6046  std::unique_ptr<ImageBuffer> temp = ImageBuffer::create(size, 1);
6047  if (!temp)
6048  return nullptr;
6049  i = std::min(m_capacity - 1, i);
6050  m_buffers[i] = WTF::move(temp);
6051 
6052  ImageBuffer* buf = m_buffers[i].get();
6053  bubbleToFront(i);
6054  return buf;
6055 }
6056 
6057 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
6058 {
6059  for (int i = idx; i > 0; --i)
6060  m_buffers[i].swap(m_buffers[i-1]);
6061 }
6062 
6063 namespace {
6064 
6065  String GetErrorString(GC3Denum error)
6066  {
6067  switch (error) {
6068  case GraphicsContext3D::INVALID_ENUM:
6069  return "INVALID_ENUM";
6070  case GraphicsContext3D::INVALID_VALUE:
6071  return "INVALID_VALUE";
6072  case GraphicsContext3D::INVALID_OPERATION:
6073  return "INVALID_OPERATION";
6074  case GraphicsContext3D::OUT_OF_MEMORY:
6075  return "OUT_OF_MEMORY";
6076  case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
6077  return "INVALID_FRAMEBUFFER_OPERATION";
6078  case GraphicsContext3D::CONTEXT_LOST_WEBGL:
6079  return "CONTEXT_LOST_WEBGL";
6080  default:
6081  return String::format("WebGL ERROR(%04x)", error);
6082  }
6083  }
6084 
6085 } // namespace anonymous
6086 
6087 void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display)
6088 {
6089  if (m_synthesizedErrorsToConsole && display == DisplayInConsole) {
6090  String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description);
6091  printGLErrorToConsole(str);
6092  }
6093  m_context->synthesizeGLError(error);
6094 }
6095 
6096 
6097 void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description)
6098 {
6099  if (m_synthesizedErrorsToConsole) {
6100  String str = String("WebGL: ") + String(functionName) + ": " + String(description);
6101  printGLErrorToConsole(str);
6102  }
6103 }
6104 
6105 void WebGLRenderingContext::applyStencilTest()
6106 {
6107  bool haveStencilBuffer = false;
6108 
6109  if (m_framebufferBinding)
6110  haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
6111  else {
6112  RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
6113  haveStencilBuffer = attributes->stencil();
6114  }
6115  enableOrDisable(GraphicsContext3D::STENCIL_TEST,
6116  m_stencilEnabled && haveStencilBuffer);
6117 }
6118 
6119 void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable)
6120 {
6121  if (enable)
6122  m_context->enable(capability);
6123  else
6124  m_context->disable(capability);
6125 }
6126 
6127 IntSize WebGLRenderingContext::clampedCanvasSize()
6128 {
6129  return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
6130  clamp(canvas()->height(), 1, m_maxViewportDims[1]));
6131 }
6132 
6133 GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
6134 {
6135  if (!supportsDrawBuffers())
6136  return 0;
6137  if (!m_maxDrawBuffers)
6138  m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
6139  if (!m_maxColorAttachments)
6140  m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
6141  // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
6142  return std::min(m_maxDrawBuffers, m_maxColorAttachments);
6143 }
6144 
6145 GC3Dint WebGLRenderingContext::getMaxColorAttachments()
6146 {
6147  if (!supportsDrawBuffers())
6148  return 0;
6149  if (!m_maxColorAttachments)
6150  m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
6151  return m_maxColorAttachments;
6152 }
6153 
6154 void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf)
6155 {
6156  m_backDrawBuffer = buf;
6157 }
6158 
6159 void WebGLRenderingContext::restoreCurrentFramebuffer()
6160 {
6161  ExceptionCode ec;
6162  bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get(), ec);
6163 }
6164 
6165 void WebGLRenderingContext::restoreCurrentTexture2D()
6166 {
6167  ExceptionCode ec;
6168  bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUnit].texture2DBinding.get(), ec);
6169 }
6170 
6171 bool WebGLRenderingContext::supportsDrawBuffers()
6172 {
6173  if (!m_drawBuffersWebGLRequirementsChecked) {
6174  m_drawBuffersWebGLRequirementsChecked = true;
6175  m_drawBuffersSupported = WebGLDrawBuffers::supported(this);
6176  }
6177  return m_drawBuffersSupported;
6178 }
6179 
6180 void WebGLRenderingContext::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
6181 {
6182  if (!validateDrawArrays("drawArraysInstanced", mode, first, count, primcount))
6183  return;
6184 
6185  if (primcount < 0) {
6186  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawArraysInstanced", "primcount < 0");
6187  return;
6188  }
6189 
6190  if (!primcount) {
6191  markContextChanged();
6192  return;
6193  }
6194 
6195  clearIfComposited();
6196 
6197  bool vertexAttrib0Simulated = false;
6198  if (!isGLES2Compliant())
6199  vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
6200  if (!isGLES2NPOTStrict())
6201  checkTextureCompleteness("drawArraysInstanced", true);
6202  UNUSED_PARAM(primcount);
6203  m_context->drawArraysInstanced(mode, first, count, primcount);
6204  if (!isGLES2Compliant() && vertexAttrib0Simulated)
6205  restoreStatesAfterVertexAttrib0Simulation();
6206  if (!isGLES2NPOTStrict())
6207  checkTextureCompleteness("drawArraysInstanced", false);
6208  markContextChanged();
6209 }
6210 
6211 void WebGLRenderingContext::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount)
6212 {
6213  unsigned numElements = 0;
6214  if (!validateDrawElements("drawElementsInstanced", mode, count, type, offset, numElements))
6215  return;
6216 
6217  if (primcount < 0) {
6218  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawElementsInstanced", "primcount < 0");
6219  return;
6220  }
6221 
6222  if (!primcount) {
6223  markContextChanged();
6224  return;
6225  }
6226 
6227  clearIfComposited();
6228 
6229  bool vertexAttrib0Simulated = false;
6230  if (!isGLES2Compliant()) {
6231  if (!numElements)
6232  validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
6233  vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
6234  }
6235  if (!isGLES2NPOTStrict())
6236  checkTextureCompleteness("drawElementsInstanced", true);
6237  m_context->drawElementsInstanced(mode, count, type, static_cast<GC3Dintptr>(offset), primcount);
6238  if (!isGLES2Compliant() && vertexAttrib0Simulated)
6239  restoreStatesAfterVertexAttrib0Simulation();
6240  if (!isGLES2NPOTStrict())
6241  checkTextureCompleteness("drawElementsInstanced", false);
6242  markContextChanged();
6243 }
6244 
6245 void WebGLRenderingContext::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
6246 {
6247  if (isContextLostOrPending())
6248  return;
6249 
6250  if (index >= m_maxVertexAttribs) {
6251  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor", "index out of range");
6252  return;
6253  }
6254 
6255  m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor);
6256  m_context->vertexAttribDivisor(index, divisor);
6257 }
6258 
6259 
626045} // namespace WebCore
626146
626247#endif // ENABLE(WEBGL)
working copy

Source/WebCore/html/canvas/WebGL1RenderingContext.h

 1/*
 2 * Copyright (C) 2009, 2014 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WebGLRenderingContext_h
 27#define WebGLRenderingContext_h
 28
 29#include "ActiveDOMObject.h"
 30#include "CanvasRenderingContext.h"
 31#include "DrawingBuffer.h"
 32#include "GraphicsContext3D.h"
 33#include "ImageBuffer.h"
 34#include "Timer.h"
 35#include "WebGLGetInfo.h"
 36#include <memory>
 37#include <runtime/Float32Array.h>
 38#include <runtime/Int32Array.h>
 39#include <wtf/text/WTFString.h>
 40
 41namespace WebCore {
 42
 43class ANGLEInstancedArrays;
 44class EXTBlendMinMax;
 45class EXTTextureFilterAnisotropic;
 46class EXTShaderTextureLOD;
 47class EXTsRGB;
 48class EXTFragDepth;
 49class HTMLImageElement;
 50class HTMLVideoElement;
 51class ImageBuffer;
 52class ImageData;
 53class IntSize;
 54class OESStandardDerivatives;
 55class OESTextureFloat;
 56class OESTextureFloatLinear;
 57class OESTextureHalfFloat;
 58class OESTextureHalfFloatLinear;
 59class OESVertexArrayObject;
 60class OESElementIndexUint;
 61class WebGLActiveInfo;
 62class WebGLBuffer;
 63class WebGLContextGroup;
 64class WebGLContextObject;
 65class WebGLCompressedTextureATC;
 66class WebGLCompressedTexturePVRTC;
 67class WebGLCompressedTextureS3TC;
 68class WebGLContextAttributes;
 69class WebGLDebugRendererInfo;
 70class WebGLDebugShaders;
 71class WebGLDepthTexture;
 72class WebGLDrawBuffers;
 73class WebGLExtension;
 74class WebGLFramebuffer;
 75class WebGLLoseContext;
 76class WebGLObject;
 77class WebGLProgram;
 78class WebGLRenderbuffer;
 79class WebGLShader;
 80class WebGLSharedObject;
 81class WebGLShaderPrecisionFormat;
 82class WebGLTexture;
 83class WebGLUniformLocation;
 84class WebGLVertexArrayObjectOES;
 85
 86typedef int ExceptionCode;
 87
 88class WebGLRenderingContext final : public CanvasRenderingContext, public ActiveDOMObject {
 89public:
 90 static std::unique_ptr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*);
 91 virtual ~WebGLRenderingContext();
 92
 93 virtual bool is3d() const override { return true; }
 94#if PLATFORM(WIN)
 95 // FIXME: Implement accelerated 3d canvas on Windows.
 96 virtual bool isAccelerated() const override { return false; }
 97#else
 98 virtual bool isAccelerated() const override { return true; }
 99#endif
 100
 101 int drawingBufferWidth() const;
 102 int drawingBufferHeight() const;
 103
 104 void activeTexture(GC3Denum texture, ExceptionCode&);
 105 void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
 106 void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&);
 107 void bindBuffer(GC3Denum target, WebGLBuffer*, ExceptionCode&);
 108 void bindFramebuffer(GC3Denum target, WebGLFramebuffer*, ExceptionCode&);
 109 void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*, ExceptionCode&);
 110 void bindTexture(GC3Denum target, WebGLTexture*, ExceptionCode&);
 111 void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
 112 void blendEquation(GC3Denum mode);
 113 void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
 114 void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
 115 void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
 116
 117 void bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode&);
 118 void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode&);
 119 void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode&);
 120 void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode&);
 121 void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode&);
 122
 123 GC3Denum checkFramebufferStatus(GC3Denum target);
 124 void clear(GC3Dbitfield mask);
 125 void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
 126 void clearDepth(GC3Dfloat);
 127 void clearStencil(GC3Dint);
 128 void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
 129 void compileShader(WebGLShader*, ExceptionCode&);
 130
 131 void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
 132 GC3Dsizei height, GC3Dint border, ArrayBufferView* data);
 133 void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 134 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
 135
 136 void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
 137 void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 138
 139 PassRefPtr<WebGLBuffer> createBuffer();
 140 PassRefPtr<WebGLFramebuffer> createFramebuffer();
 141 PassRefPtr<WebGLProgram> createProgram();
 142 PassRefPtr<WebGLRenderbuffer> createRenderbuffer();
 143 PassRefPtr<WebGLShader> createShader(GC3Denum type, ExceptionCode&);
 144 PassRefPtr<WebGLTexture> createTexture();
 145
 146 void cullFace(GC3Denum mode);
 147
 148 void deleteBuffer(WebGLBuffer*);
 149 void deleteFramebuffer(WebGLFramebuffer*);
 150 void deleteProgram(WebGLProgram*);
 151 void deleteRenderbuffer(WebGLRenderbuffer*);
 152 void deleteShader(WebGLShader*);
 153 void deleteTexture(WebGLTexture*);
 154
 155 void depthFunc(GC3Denum);
 156 void depthMask(GC3Dboolean);
 157 void depthRange(GC3Dfloat zNear, GC3Dfloat zFar);
 158 void detachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
 159 void disable(GC3Denum cap);
 160 void disableVertexAttribArray(GC3Duint index, ExceptionCode&);
 161 void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode&);
 162 void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode&);
 163
 164 void enable(GC3Denum cap);
 165 void enableVertexAttribArray(GC3Duint index, ExceptionCode&);
 166 void finish();
 167 void flush();
 168 void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*, ExceptionCode&);
 169 void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level, ExceptionCode&);
 170 void frontFace(GC3Denum mode);
 171 void generateMipmap(GC3Denum target);
 172
 173 PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index, ExceptionCode&);
 174 PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index, ExceptionCode&);
 175 bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader>>&, ExceptionCode&);
 176 GC3Dint getAttribLocation(WebGLProgram*, const String& name);
 177 WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
 178 PassRefPtr<WebGLContextAttributes> getContextAttributes();
 179 GC3Denum getError();
 180 WebGLExtension* getExtension(const String& name);
 181 WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&);
 182 WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&);
 183 WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname, ExceptionCode&);
 184 String getProgramInfoLog(WebGLProgram*, ExceptionCode&);
 185 WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
 186 WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname, ExceptionCode&);
 187 String getShaderInfoLog(WebGLShader*, ExceptionCode&);
 188 PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode&);
 189 String getShaderSource(WebGLShader*, ExceptionCode&);
 190 Vector<String> getSupportedExtensions();
 191 WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
 192 WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*, ExceptionCode&);
 193 PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&, ExceptionCode&);
 194 WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode&);
 195 long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
 196
 197 void hint(GC3Denum target, GC3Denum mode);
 198 GC3Dboolean isBuffer(WebGLBuffer*);
 199 bool isContextLost() const;
 200 GC3Dboolean isEnabled(GC3Denum cap);
 201 GC3Dboolean isFramebuffer(WebGLFramebuffer*);
 202 GC3Dboolean isProgram(WebGLProgram*);
 203 GC3Dboolean isRenderbuffer(WebGLRenderbuffer*);
 204 GC3Dboolean isShader(WebGLShader*);
 205 GC3Dboolean isTexture(WebGLTexture*);
 206
 207 void lineWidth(GC3Dfloat);
 208 void linkProgram(WebGLProgram*, ExceptionCode&);
 209 void pixelStorei(GC3Denum pname, GC3Dint param);
 210 void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
 211 void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&);
 212 void releaseShaderCompiler();
 213 void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
 214 void sampleCoverage(GC3Dfloat value, GC3Dboolean invert);
 215 void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 216 void shaderSource(WebGLShader*, const String&, ExceptionCode&);
 217 void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
 218 void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
 219 void stencilMask(GC3Duint);
 220 void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
 221 void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
 222 void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
 223
 224 void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 225 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 226 GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
 227 void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 228 GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
 229 void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 230 GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
 231 void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 232 GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
 233#if ENABLE(VIDEO)
 234 void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 235 GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
 236#endif
 237
 238 void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
 239 void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
 240
 241 void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 242 GC3Dsizei width, GC3Dsizei height,
 243 GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
 244 void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 245 GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
 246 void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 247 GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
 248 void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 249 GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
 250#if ENABLE(VIDEO)
 251 void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 252 GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
 253#endif
 254
 255 void uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode&);
 256 void uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 257 void uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 258 void uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode&);
 259 void uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 260 void uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 261 void uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode&);
 262 void uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 263 void uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 264 void uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode&);
 265 void uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 266 void uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 267 void uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode&);
 268 void uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 269 void uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 270 void uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode&);
 271 void uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 272 void uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 273 void uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode&);
 274 void uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 275 void uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 276 void uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode&);
 277 void uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 278 void uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 279 void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
 280 void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
 281 void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
 282 void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
 283 void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
 284 void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
 285
 286 void useProgram(WebGLProgram*, ExceptionCode&);
 287 void validateProgram(WebGLProgram*, ExceptionCode&);
 288
 289 void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
 290 void vertexAttrib1fv(GC3Duint index, Float32Array* values);
 291 void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 292 void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
 293 void vertexAttrib2fv(GC3Duint index, Float32Array* values);
 294 void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 295 void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
 296 void vertexAttrib3fv(GC3Duint index, Float32Array* values);
 297 void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 298 void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
 299 void vertexAttrib4fv(GC3Duint index, Float32Array* values);
 300 void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 301 void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
 302 GC3Dsizei stride, long long offset, ExceptionCode&);
 303
 304 void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 305
 306 // WEBKIT_lose_context support
 307 enum LostContextMode {
 308 // Lost context occurred at the graphics system level.
 309 RealLostContext,
 310
 311 // Lost context provoked by WEBKIT_lose_context.
 312 SyntheticLostContext
 313 };
 314 void forceLostContext(LostContextMode);
 315 void forceRestoreContext();
 316 void loseContextImpl(LostContextMode);
 317
 318 GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
 319 WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
 320 virtual PlatformLayer* platformLayer() const override;
 321
 322 void reshape(int width, int height);
 323
 324 void markLayerComposited();
 325 virtual void paintRenderingResultsToCanvas() override;
 326 PassRefPtr<ImageData> paintRenderingResultsToImageData();
 327
 328 void removeSharedObject(WebGLSharedObject*);
 329 void removeContextObject(WebGLContextObject*);
 330
 331 unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; }
 332
 333 // ANGLE_instanced_arrays extension functions.
 334 void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
 335 void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount);
 336 void vertexAttribDivisor(GC3Duint index, GC3Duint divisor);
 337
 338private:
 339 friend class WebGLDrawBuffers;
 340 friend class WebGLFramebuffer;
 341 friend class WebGLObject;
 342 friend class OESVertexArrayObject;
 343 friend class WebGLDebugShaders;
 344 friend class WebGLCompressedTextureATC;
 345 friend class WebGLCompressedTexturePVRTC;
 346 friend class WebGLCompressedTextureS3TC;
 347 friend class WebGLRenderingContextErrorMessageCallback;
 348 friend class WebGLVertexArrayObjectOES;
 349
 350 WebGLRenderingContext(HTMLCanvasElement*, GraphicsContext3D::Attributes);
 351 WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes);
 352 void initializeNewContext();
 353 void setupFlags();
 354
 355 // ActiveDOMObject
 356 virtual bool hasPendingActivity() const override;
 357 virtual void stop() override;
 358 virtual const char* activeDOMObjectName() const override { return "WebGLRenderingContext"; }
 359
 360 void addSharedObject(WebGLSharedObject*);
 361 void addContextObject(WebGLContextObject*);
 362 void detachAndRemoveAllObjects();
 363
 364 void destroyGraphicsContext3D();
 365 void markContextChanged();
 366
 367 // Query whether it is built on top of compliant GLES2 implementation.
 368 bool isGLES2Compliant() { return m_isGLES2Compliant; }
 369 // Query if the GL implementation is NPOT strict.
 370 bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; }
 371 // Query if the GL implementation generates errors on out-of-bounds buffer accesses.
 372 bool isErrorGeneratedOnOutOfBoundsAccesses() { return m_isErrorGeneratedOnOutOfBoundsAccesses; }
 373 // Query if the GL implementation initializes textures/renderbuffers to 0.
 374 bool isResourceSafe() { return m_isResourceSafe; }
 375 // Query if depth_stencil buffer is supported.
 376 bool isDepthStencilSupported() { return m_isDepthStencilSupported; }
 377
 378 // Helper to return the size in bytes of OpenGL data types
 379 // like GL_FLOAT, GL_INT, etc.
 380 unsigned int sizeInBytes(GC3Denum type);
 381
 382 // Basic validation of count and offset against number of elements in element array buffer
 383 bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
 384
 385 // Conservative but quick index validation
 386 bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired);
 387
 388 // Precise but slow index validation -- only done if conservative checks fail
 389 bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired);
 390 bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0);
 391
 392 bool validateWebGLObject(const char*, WebGLObject*);
 393
 394 bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
 395 bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount);
 396
 397 // Adds a compressed texture format.
 398 void addCompressedTextureFormat(GC3Denum);
 399
 400 PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, int deviceScaleFactor);
 401
 402#if ENABLE(VIDEO)
 403 PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy, ExceptionCode&);
 404#endif
 405
 406 RefPtr<GraphicsContext3D> m_context;
 407 RefPtr<WebGLContextGroup> m_contextGroup;
 408
 409 // Optional structure for rendering to a DrawingBuffer, instead of directly
 410 // to the back-buffer of m_context.
 411 RefPtr<DrawingBuffer> m_drawingBuffer;
 412
 413 // Dispatches a context lost event once it is determined that one is needed.
 414 // This is used both for synthetic and real context losses. For real ones, it's
 415 // likely that there's no JavaScript on the stack, but that might be dependent
 416 // on how exactly the platform discovers that the context was lost. For better
 417 // portability we always defer the dispatch of the event.
 418 Timer m_dispatchContextLostEventTimer;
 419 bool m_restoreAllowed;
 420 Timer m_restoreTimer;
 421
 422 bool m_needsUpdate;
 423 bool m_markedCanvasDirty;
 424 HashSet<WebGLContextObject*> m_contextObjects;
 425
 426 // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
 427 RefPtr<WebGLBuffer> m_boundArrayBuffer;
 428
 429 RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject;
 430 RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject;
 431 void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject)
 432 {
 433 if (arrayObject)
 434 m_boundVertexArrayObject = arrayObject;
 435 else
 436 m_boundVertexArrayObject = m_defaultVertexArrayObject;
 437 }
 438
 439 class VertexAttribValue {
 440 public:
 441 VertexAttribValue()
 442 {
 443 initValue();
 444 }
 445
 446 void initValue()
 447 {
 448 value[0] = 0.0f;
 449 value[1] = 0.0f;
 450 value[2] = 0.0f;
 451 value[3] = 1.0f;
 452 }
 453
 454 GC3Dfloat value[4];
 455 };
 456 Vector<VertexAttribValue> m_vertexAttribValue;
 457 unsigned m_maxVertexAttribs;
 458 RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
 459 long m_vertexAttrib0BufferSize;
 460 GC3Dfloat m_vertexAttrib0BufferValue[4];
 461 bool m_forceAttrib0BufferRefill;
 462 bool m_vertexAttrib0UsedBefore;
 463
 464 RefPtr<WebGLProgram> m_currentProgram;
 465 RefPtr<WebGLFramebuffer> m_framebufferBinding;
 466 RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
 467 struct TextureUnitState {
 468 RefPtr<WebGLTexture> texture2DBinding;
 469 RefPtr<WebGLTexture> textureCubeMapBinding;
 470 };
 471 Vector<TextureUnitState> m_textureUnits;
 472 unsigned long m_activeTextureUnit;
 473
 474 RefPtr<WebGLTexture> m_blackTexture2D;
 475 RefPtr<WebGLTexture> m_blackTextureCubeMap;
 476
 477 Vector<GC3Denum> m_compressedTextureFormats;
 478
 479 // Fixed-size cache of reusable image buffers for video texImage2D calls.
 480 class LRUImageBufferCache {
 481 public:
 482 LRUImageBufferCache(int capacity);
 483 // The pointer returned is owned by the image buffer map.
 484 ImageBuffer* imageBuffer(const IntSize& size);
 485 private:
 486 void bubbleToFront(int idx);
 487 std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers;
 488 int m_capacity;
 489 };
 490 LRUImageBufferCache m_generatedImageCache;
 491
 492 GC3Dint m_maxTextureSize;
 493 GC3Dint m_maxCubeMapTextureSize;
 494 GC3Dint m_maxRenderbufferSize;
 495 GC3Dint m_maxViewportDims[2];
 496 GC3Dint m_maxTextureLevel;
 497 GC3Dint m_maxCubeMapTextureLevel;
 498
 499 GC3Dint m_maxDrawBuffers;
 500 GC3Dint m_maxColorAttachments;
 501 GC3Denum m_backDrawBuffer;
 502 bool m_drawBuffersWebGLRequirementsChecked;
 503 bool m_drawBuffersSupported;
 504
 505 GC3Dint m_packAlignment;
 506 GC3Dint m_unpackAlignment;
 507 bool m_unpackFlipY;
 508 bool m_unpackPremultiplyAlpha;
 509 GC3Denum m_unpackColorspaceConversion;
 510 bool m_contextLost;
 511 LostContextMode m_contextLostMode;
 512 GraphicsContext3D::Attributes m_attributes;
 513
 514 bool m_layerCleared;
 515 GC3Dfloat m_clearColor[4];
 516 bool m_scissorEnabled;
 517 GC3Dfloat m_clearDepth;
 518 GC3Dint m_clearStencil;
 519 GC3Dboolean m_colorMask[4];
 520 GC3Dboolean m_depthMask;
 521
 522 bool m_stencilEnabled;
 523 GC3Duint m_stencilMask, m_stencilMaskBack;
 524 GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
 525 GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack;
 526
 527 bool m_isGLES2Compliant;
 528 bool m_isGLES2NPOTStrict;
 529 bool m_isErrorGeneratedOnOutOfBoundsAccesses;
 530 bool m_isResourceSafe;
 531 bool m_isDepthStencilSupported;
 532 bool m_isRobustnessEXTSupported;
 533
 534 bool m_synthesizedErrorsToConsole;
 535 int m_numGLErrorsToConsoleAllowed;
 536
 537 // A WebGLRenderingContext can be created in a state where it appears as
 538 // a valid and active context, but will not execute any important operations
 539 // until its load policy is completely resolved.
 540 bool m_isPendingPolicyResolution;
 541 bool m_hasRequestedPolicyResolution;
 542 bool isContextLostOrPending();
 543
 544 // Enabled extension objects.
 545 std::unique_ptr<EXTFragDepth> m_extFragDepth;
 546 std::unique_ptr<EXTBlendMinMax> m_extBlendMinMax;
 547 std::unique_ptr<EXTsRGB> m_extsRGB;
 548 std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic;
 549 std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD;
 550 std::unique_ptr<OESTextureFloat> m_oesTextureFloat;
 551 std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear;
 552 std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat;
 553 std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear;
 554 std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives;
 555 std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject;
 556 std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint;
 557 std::unique_ptr<WebGLLoseContext> m_webglLoseContext;
 558 std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo;
 559 std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders;
 560 std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC;
 561 std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC;
 562 std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC;
 563 std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture;
 564 std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers;
 565 std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays;
 566
 567 // Helpers for getParameter and others
 568 WebGLGetInfo getBooleanParameter(GC3Denum);
 569 WebGLGetInfo getBooleanArrayParameter(GC3Denum);
 570 WebGLGetInfo getFloatParameter(GC3Denum);
 571 WebGLGetInfo getIntParameter(GC3Denum);
 572 WebGLGetInfo getUnsignedIntParameter(GC3Denum);
 573 WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum);
 574 WebGLGetInfo getWebGLIntArrayParameter(GC3Denum);
 575
 576 // Clear the backbuffer if it was composited since the last operation.
 577 // clearMask is set to the bitfield of any clear that would happen anyway at this time
 578 // and the function returns true if that clear is now unnecessary.
 579 bool clearIfComposited(GC3Dbitfield clearMask = 0);
 580
 581 // Helper to restore state that clearing the framebuffer may destroy.
 582 void restoreStateAfterClear();
 583
 584 void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
 585 void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
 586 void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
 587 void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
 588
 589 void checkTextureCompleteness(const char*, bool);
 590
 591 void createFallbackBlackTextures1x1();
 592
 593 // Helper function for copyTex{Sub}Image, check whether the internalformat
 594 // and the color buffer format of the current bound framebuffer combination
 595 // is valid.
 596 bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
 597 GC3Denum colorBufferFormat);
 598
 599 // Helper function to get the bound framebuffer's color buffer format.
 600 GC3Denum getBoundFramebufferColorFormat();
 601
 602 // Helper function to get the bound framebuffer's width.
 603 int getBoundFramebufferWidth();
 604
 605 // Helper function to get the bound framebuffer's height.
 606 int getBoundFramebufferHeight();
 607
 608 // Helper function to verify limits on the length of uniform and attribute locations.
 609 bool validateLocationLength(const char* functionName, const String&);
 610
 611 // Helper function to check if size is non-negative.
 612 // Generate GL error and return false for negative inputs; otherwise, return true.
 613 bool validateSize(const char* functionName, GC3Dint x, GC3Dint y);
 614
 615 // Helper function to check if all characters in the string belong to the
 616 // ASCII subset as defined in GLSL ES 1.0 spec section 3.1.
 617 bool validateString(const char* functionName, const String&);
 618
 619 // Helper function to check target and texture bound to the target.
 620 // Generate GL errors and return 0 if target is invalid or texture bound is
 621 // null. Otherwise, return the texture bound to the target.
 622 WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap);
 623
 624 // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
 625 // Generates GL error and returns false if parameters are invalid.
 626 bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
 627
 628 // Helper function to check input level for functions {copy}Tex{Sub}Image.
 629 // Generates GL error and returns false if level is invalid.
 630 bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
 631
 632 enum TexFuncValidationFunctionType {
 633 NotTexSubImage2D,
 634 TexSubImage2D,
 635 };
 636
 637 enum TexFuncValidationSourceType {
 638 SourceArrayBufferView,
 639 SourceImageData,
 640 SourceHTMLImageElement,
 641 SourceHTMLCanvasElement,
 642 SourceHTMLVideoElement,
 643 };
 644
 645 // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid.
 646 // Otherwise, it would return quickly without doing other work.
 647 bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
 648 GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset);
 649
 650 // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
 651 // Generates GL error and returns false if parameters are invalid.
 652 bool validateTexFuncParameters(const char* functionName,
 653 TexFuncValidationFunctionType,
 654 GC3Denum target, GC3Dint level,
 655 GC3Denum internalformat,
 656 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 657 GC3Denum format, GC3Denum type);
 658
 659 enum NullDisposition {
 660 NullAllowed,
 661 NullNotAllowed
 662 };
 663
 664 // Helper function to validate that the given ArrayBufferView
 665 // is of the correct type and contains enough data for the texImage call.
 666 // Generates GL error and returns false if parameters are invalid.
 667 bool validateTexFuncData(const char* functionName, GC3Dint level,
 668 GC3Dsizei width, GC3Dsizei height,
 669 GC3Denum format, GC3Denum type,
 670 ArrayBufferView* pixels,
 671 NullDisposition);
 672
 673 // Helper function to validate a given texture format is settable as in
 674 // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
 675 // copyTexSubImage2D.
 676 // Generates GL error and returns false if the format is not settable.
 677 bool validateSettableTexFormat(const char* functionName, GC3Denum format);
 678
 679 // Helper function to validate compressed texture data is correct size
 680 // for the given format and dimensions.
 681 bool validateCompressedTexFuncData(const char* functionName,
 682 GC3Dsizei width, GC3Dsizei height,
 683 GC3Denum format, ArrayBufferView* pixels);
 684
 685 // Helper function for validating compressed texture formats.
 686 bool validateCompressedTexFormat(GC3Denum format);
 687
 688 // Helper function to validate compressed texture dimensions are valid for
 689 // the given format.
 690 bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
 691
 692 // Helper function to validate compressed texture dimensions are valid for
 693 // the given format.
 694 bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 695 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
 696
 697 // Helper function to validate mode for draw{Arrays/Elements}.
 698 bool validateDrawMode(const char* functionName, GC3Denum);
 699
 700 // Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
 701 bool validateStencilSettings(const char* functionName);
 702
 703 // Helper function to validate stencil func.
 704 bool validateStencilFunc(const char* functionName, GC3Denum);
 705
 706 // Helper function for texParameterf and texParameteri.
 707 void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
 708
 709 // Helper function to print GL errors to console.
 710 void printGLErrorToConsole(const String&);
 711 void printGLWarningToConsole(const char* function, const char* reason);
 712
 713 // Helper function to print warnings to console. Currently
 714 // used only to warn about use of obsolete functions.
 715 void printWarningToConsole(const String&);
 716
 717 // Helper function to validate input parameters for framebuffer functions.
 718 // Generate GL error if parameters are illegal.
 719 bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment);
 720
 721 // Helper function to validate blend equation mode.
 722 bool validateBlendEquation(const char* functionName, GC3Denum);
 723
 724 // Helper function to validate blend func factors.
 725 bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
 726
 727 // Helper function to validate a GL capability.
 728 bool validateCapability(const char* functionName, GC3Denum);
 729
 730 // Helper function to validate input parameters for uniform functions.
 731 bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod);
 732 bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod);
 733 bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod);
 734 bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod);
 735 bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod);
 736
 737 // Helper function to validate parameters for bufferData.
 738 // Return the current bound buffer to target, or 0 if parameters are invalid.
 739 WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage);
 740
 741 // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin.
 742 bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&);
 743
 744 // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin.
 745 bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&);
 746
 747#if ENABLE(VIDEO)
 748 // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin.
 749 bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&);
 750#endif
 751
 752 // Helper functions for vertexAttribNf{v}.
 753 void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat);
 754 void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize);
 755 void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize);
 756
 757 // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
 758 // Return false if caller should return without further processing.
 759 bool deleteObject(WebGLObject*);
 760
 761 // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram.
 762 // If the object has already been deleted, set deleted to true upon return.
 763 // Return false if caller should return without further processing.
 764 bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted);
 765
 766 // Helpers for simulating vertexAttrib0
 767 void initVertexAttrib0();
 768 bool simulateVertexAttrib0(GC3Dsizei numVertex);
 769 void restoreStatesAfterVertexAttrib0Simulation();
 770
 771 void dispatchContextLostEvent();
 772 // Helper for restoration after context lost.
 773 void maybeRestoreContext();
 774
 775 // Determine if we are running privileged code in the browser, for example,
 776 // a Safari or Chrome extension.
 777 bool allowPrivilegedExtensions() const;
 778
 779 enum ConsoleDisplayPreference {
 780 DisplayInConsole,
 781 DontDisplayInConsole
 782 };
 783
 784 // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message
 785 // to the JavaScript console.
 786 void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole);
 787
 788 String ensureNotNull(const String&) const;
 789
 790 // Enable or disable stencil test based on user setting and
 791 // whether the current FBO has a stencil buffer.
 792 void applyStencilTest();
 793
 794 // Helper for enabling or disabling a capability.
 795 void enableOrDisable(GC3Denum capability, bool enable);
 796
 797 // Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
 798 IntSize clampedCanvasSize();
 799
 800 // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0.
 801 // Later, return the cached value.
 802 GC3Dint getMaxDrawBuffers();
 803 GC3Dint getMaxColorAttachments();
 804
 805 void setBackDrawBuffer(GC3Denum);
 806
 807 void restoreCurrentFramebuffer();
 808 void restoreCurrentTexture2D();
 809
 810 // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
 811 bool supportsDrawBuffers();
 812};
 813
 814} // namespace WebCore
 815
 816#endif
176994

Source/WebCore/html/canvas/WebGL1RenderingContext.h

11/*
2  * Copyright (C) 2009, 2014 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2626#ifndef WebGLRenderingContext_h
2727#define WebGLRenderingContext_h
2828
29 #include "ActiveDOMObject.h"
30 #include "CanvasRenderingContext.h"
31 #include "DrawingBuffer.h"
32 #include "GraphicsContext3D.h"
33 #include "ImageBuffer.h"
34 #include "Timer.h"
35 #include "WebGLGetInfo.h"
36 #include <memory>
37 #include <runtime/Float32Array.h>
38 #include <runtime/Int32Array.h>
39 #include <wtf/text/WTFString.h>
 29#include "WebGLRenderingContextBase.h"
4030
4131namespace WebCore {
4232
43 class ANGLEInstancedArrays;
44 class EXTTextureFilterAnisotropic;
45 class EXTShaderTextureLOD;
46 class HTMLImageElement;
47 class HTMLVideoElement;
48 class ImageBuffer;
49 class ImageData;
50 class IntSize;
51 class OESStandardDerivatives;
52 class OESTextureFloat;
53 class OESTextureFloatLinear;
54 class OESTextureHalfFloat;
55 class OESTextureHalfFloatLinear;
56 class OESVertexArrayObject;
57 class OESElementIndexUint;
58 class WebGLActiveInfo;
59 class WebGLBuffer;
60 class WebGLContextGroup;
61 class WebGLContextObject;
62 class WebGLCompressedTextureATC;
63 class WebGLCompressedTexturePVRTC;
64 class WebGLCompressedTextureS3TC;
65 class WebGLContextAttributes;
66 class WebGLDebugRendererInfo;
67 class WebGLDebugShaders;
68 class WebGLDepthTexture;
69 class WebGLDrawBuffers;
70 class WebGLExtension;
71 class WebGLFramebuffer;
72 class WebGLLoseContext;
73 class WebGLObject;
74 class WebGLProgram;
75 class WebGLRenderbuffer;
76 class WebGLShader;
77 class WebGLSharedObject;
78 class WebGLShaderPrecisionFormat;
79 class WebGLTexture;
80 class WebGLUniformLocation;
81 class WebGLVertexArrayObjectOES;
82 
83 typedef int ExceptionCode;
84 
85 class WebGLRenderingContext final : public CanvasRenderingContext, public ActiveDOMObject {
 33class WebGL1RenderingContext final : public WebGLRenderingContextBase {
8634public:
87  static std::unique_ptr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*);
88  virtual ~WebGLRenderingContext();
89 
90  virtual bool is3d() const override { return true; }
91 #if PLATFORM(WIN)
92  // FIXME: Implement accelerated 3d canvas on Windows.
93  virtual bool isAccelerated() const override { return false; }
94 #else
95  virtual bool isAccelerated() const override { return true; }
96 #endif
97 
98  int drawingBufferWidth() const;
99  int drawingBufferHeight() const;
100 
101  void activeTexture(GC3Denum texture, ExceptionCode&);
102  void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
103  void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&);
104  void bindBuffer(GC3Denum target, WebGLBuffer*, ExceptionCode&);
105  void bindFramebuffer(GC3Denum target, WebGLFramebuffer*, ExceptionCode&);
106  void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*, ExceptionCode&);
107  void bindTexture(GC3Denum target, WebGLTexture*, ExceptionCode&);
108  void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
109  void blendEquation(GC3Denum mode);
110  void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
111  void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
112  void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
113 
114  void bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode&);
115  void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode&);
116  void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode&);
117  void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode&);
118  void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode&);
119 
120  GC3Denum checkFramebufferStatus(GC3Denum target);
121  void clear(GC3Dbitfield mask);
122  void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
123  void clearDepth(GC3Dfloat);
124  void clearStencil(GC3Dint);
125  void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
126  void compileShader(WebGLShader*, ExceptionCode&);
127 
128  void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
129  GC3Dsizei height, GC3Dint border, ArrayBufferView* data);
130  void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
131  GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
132 
133  void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
134  void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
135 
136  PassRefPtr<WebGLBuffer> createBuffer();
137  PassRefPtr<WebGLFramebuffer> createFramebuffer();
138  PassRefPtr<WebGLProgram> createProgram();
139  PassRefPtr<WebGLRenderbuffer> createRenderbuffer();
140  PassRefPtr<WebGLShader> createShader(GC3Denum type, ExceptionCode&);
141  PassRefPtr<WebGLTexture> createTexture();
142 
143  void cullFace(GC3Denum mode);
144 
145  void deleteBuffer(WebGLBuffer*);
146  void deleteFramebuffer(WebGLFramebuffer*);
147  void deleteProgram(WebGLProgram*);
148  void deleteRenderbuffer(WebGLRenderbuffer*);
149  void deleteShader(WebGLShader*);
150  void deleteTexture(WebGLTexture*);
151 
152  void depthFunc(GC3Denum);
153  void depthMask(GC3Dboolean);
154  void depthRange(GC3Dfloat zNear, GC3Dfloat zFar);
155  void detachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
156  void disable(GC3Denum cap);
157  void disableVertexAttribArray(GC3Duint index, ExceptionCode&);
158  void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode&);
159  void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode&);
160 
161  void enable(GC3Denum cap);
162  void enableVertexAttribArray(GC3Duint index, ExceptionCode&);
163  void finish();
164  void flush();
165  void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*, ExceptionCode&);
166  void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level, ExceptionCode&);
167  void frontFace(GC3Denum mode);
168  void generateMipmap(GC3Denum target);
169 
170  PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index, ExceptionCode&);
171  PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index, ExceptionCode&);
172  bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader>>&, ExceptionCode&);
173  GC3Dint getAttribLocation(WebGLProgram*, const String& name);
174  WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
175  PassRefPtr<WebGLContextAttributes> getContextAttributes();
176  GC3Denum getError();
177  WebGLExtension* getExtension(const String& name);
178  WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&);
179  WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&);
180  WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname, ExceptionCode&);
181  String getProgramInfoLog(WebGLProgram*, ExceptionCode&);
182  WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
183  WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname, ExceptionCode&);
184  String getShaderInfoLog(WebGLShader*, ExceptionCode&);
185  PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode&);
186  String getShaderSource(WebGLShader*, ExceptionCode&);
187  Vector<String> getSupportedExtensions();
188  WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
189  WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*, ExceptionCode&);
190  PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&, ExceptionCode&);
191  WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode&);
192  long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
193 
194  void hint(GC3Denum target, GC3Denum mode);
195  GC3Dboolean isBuffer(WebGLBuffer*);
196  bool isContextLost() const;
197  GC3Dboolean isEnabled(GC3Denum cap);
198  GC3Dboolean isFramebuffer(WebGLFramebuffer*);
199  GC3Dboolean isProgram(WebGLProgram*);
200  GC3Dboolean isRenderbuffer(WebGLRenderbuffer*);
201  GC3Dboolean isShader(WebGLShader*);
202  GC3Dboolean isTexture(WebGLTexture*);
203 
204  void lineWidth(GC3Dfloat);
205  void linkProgram(WebGLProgram*, ExceptionCode&);
206  void pixelStorei(GC3Denum pname, GC3Dint param);
207  void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
208  void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&);
209  void releaseShaderCompiler();
210  void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
211  void sampleCoverage(GC3Dfloat value, GC3Dboolean invert);
212  void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
213  void shaderSource(WebGLShader*, const String&, ExceptionCode&);
214  void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
215  void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
216  void stencilMask(GC3Duint);
217  void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
218  void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
219  void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
220 
221  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
222  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
223  GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
224  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
225  GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
226  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
227  GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
228  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
229  GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
230 #if ENABLE(VIDEO)
231  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
232  GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
233 #endif
234 
235  void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
236  void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
237 
238  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
239  GC3Dsizei width, GC3Dsizei height,
240  GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
241  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
242  GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
243  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
244  GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
245  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
246  GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
247 #if ENABLE(VIDEO)
248  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
249  GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
250 #endif
251 
252  void uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode&);
253  void uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
254  void uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
255  void uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode&);
256  void uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
257  void uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
258  void uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode&);
259  void uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
260  void uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
261  void uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode&);
262  void uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
263  void uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
264  void uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode&);
265  void uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
266  void uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
267  void uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode&);
268  void uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
269  void uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
270  void uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode&);
271  void uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
272  void uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
273  void uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode&);
274  void uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
275  void uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
276  void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
277  void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
278  void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
279  void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
280  void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
281  void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
282 
283  void useProgram(WebGLProgram*, ExceptionCode&);
284  void validateProgram(WebGLProgram*, ExceptionCode&);
285 
286  void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
287  void vertexAttrib1fv(GC3Duint index, Float32Array* values);
288  void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
289  void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
290  void vertexAttrib2fv(GC3Duint index, Float32Array* values);
291  void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
292  void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
293  void vertexAttrib3fv(GC3Duint index, Float32Array* values);
294  void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
295  void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
296  void vertexAttrib4fv(GC3Duint index, Float32Array* values);
297  void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
298  void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
299  GC3Dsizei stride, long long offset, ExceptionCode&);
300 
301  void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
302 
303  // WEBKIT_lose_context support
304  enum LostContextMode {
305  // Lost context occurred at the graphics system level.
306  RealLostContext,
307 
308  // Lost context provoked by WEBKIT_lose_context.
309  SyntheticLostContext
310  };
311  void forceLostContext(LostContextMode);
312  void forceRestoreContext();
313  void loseContextImpl(LostContextMode);
314 
315  GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
316  WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
317  virtual PlatformLayer* platformLayer() const override;
318 
319  void reshape(int width, int height);
320 
321  void markLayerComposited();
322  virtual void paintRenderingResultsToCanvas() override;
323  PassRefPtr<ImageData> paintRenderingResultsToImageData();
324 
325  void removeSharedObject(WebGLSharedObject*);
326  void removeContextObject(WebGLContextObject*);
327 
328  unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; }
329 
330  // ANGLE_instanced_arrays extension functions.
331  void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
332  void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount);
333  void vertexAttribDivisor(GC3Duint index, GC3Duint divisor);
334 
335 private:
336  friend class WebGLDrawBuffers;
337  friend class WebGLFramebuffer;
338  friend class WebGLObject;
339  friend class OESVertexArrayObject;
340  friend class WebGLDebugShaders;
341  friend class WebGLCompressedTextureATC;
342  friend class WebGLCompressedTexturePVRTC;
343  friend class WebGLCompressedTextureS3TC;
344  friend class WebGLRenderingContextErrorMessageCallback;
345  friend class WebGLVertexArrayObjectOES;
346 
347  WebGLRenderingContext(HTMLCanvasElement*, GraphicsContext3D::Attributes);
348  WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes);
349  void initializeNewContext();
350  void setupFlags();
351 
352  // ActiveDOMObject
353  virtual bool hasPendingActivity() const override;
354  virtual void stop() override;
355 
356  void addSharedObject(WebGLSharedObject*);
357  void addContextObject(WebGLContextObject*);
358  void detachAndRemoveAllObjects();
359 
360  void destroyGraphicsContext3D();
361  void markContextChanged();
362 
363  // Query whether it is built on top of compliant GLES2 implementation.
364  bool isGLES2Compliant() { return m_isGLES2Compliant; }
365  // Query if the GL implementation is NPOT strict.
366  bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; }
367  // Query if the GL implementation generates errors on out-of-bounds buffer accesses.
368  bool isErrorGeneratedOnOutOfBoundsAccesses() { return m_isErrorGeneratedOnOutOfBoundsAccesses; }
369  // Query if the GL implementation initializes textures/renderbuffers to 0.
370  bool isResourceSafe() { return m_isResourceSafe; }
371  // Query if depth_stencil buffer is supported.
372  bool isDepthStencilSupported() { return m_isDepthStencilSupported; }
373 
374  // Helper to return the size in bytes of OpenGL data types
375  // like GL_FLOAT, GL_INT, etc.
376  unsigned int sizeInBytes(GC3Denum type);
377 
378  // Basic validation of count and offset against number of elements in element array buffer
379  bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
380 
381  // Conservative but quick index validation
382  bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired);
383 
384  // Precise but slow index validation -- only done if conservative checks fail
385  bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired);
386  bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0);
387 
388  bool validateWebGLObject(const char*, WebGLObject*);
389 
390  bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
391  bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements);
392 
393  // Adds a compressed texture format.
394  void addCompressedTextureFormat(GC3Denum);
395 
396  PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, int deviceScaleFactor);
397 
398 #if ENABLE(VIDEO)
399  PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy, ExceptionCode&);
400 #endif
401 
402  RefPtr<GraphicsContext3D> m_context;
403  RefPtr<WebGLContextGroup> m_contextGroup;
404 
405  // Optional structure for rendering to a DrawingBuffer, instead of directly
406  // to the back-buffer of m_context.
407  RefPtr<DrawingBuffer> m_drawingBuffer;
408 
409  // Dispatches a context lost event once it is determined that one is needed.
410  // This is used both for synthetic and real context losses. For real ones, it's
411  // likely that there's no JavaScript on the stack, but that might be dependent
412  // on how exactly the platform discovers that the context was lost. For better
413  // portability we always defer the dispatch of the event.
414  Timer m_dispatchContextLostEventTimer;
415  bool m_restoreAllowed;
416  Timer m_restoreTimer;
417 
418  bool m_needsUpdate;
419  bool m_markedCanvasDirty;
420  HashSet<WebGLContextObject*> m_contextObjects;
421 
422  // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
423  RefPtr<WebGLBuffer> m_boundArrayBuffer;
424 
425  RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject;
426  RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject;
427  void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject)
428  {
429  if (arrayObject)
430  m_boundVertexArrayObject = arrayObject;
431  else
432  m_boundVertexArrayObject = m_defaultVertexArrayObject;
433  }
434 
435  class VertexAttribValue {
436  public:
437  VertexAttribValue()
438  {
439  initValue();
440  }
441 
442  void initValue()
443  {
444  value[0] = 0.0f;
445  value[1] = 0.0f;
446  value[2] = 0.0f;
447  value[3] = 1.0f;
448  }
449 
450  GC3Dfloat value[4];
451  };
452  Vector<VertexAttribValue> m_vertexAttribValue;
453  unsigned m_maxVertexAttribs;
454  RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
455  long m_vertexAttrib0BufferSize;
456  GC3Dfloat m_vertexAttrib0BufferValue[4];
457  bool m_forceAttrib0BufferRefill;
458  bool m_vertexAttrib0UsedBefore;
459 
460  RefPtr<WebGLProgram> m_currentProgram;
461  RefPtr<WebGLFramebuffer> m_framebufferBinding;
462  RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
463  struct TextureUnitState {
464  RefPtr<WebGLTexture> texture2DBinding;
465  RefPtr<WebGLTexture> textureCubeMapBinding;
466  };
467  Vector<TextureUnitState> m_textureUnits;
468  unsigned long m_activeTextureUnit;
469 
470  RefPtr<WebGLTexture> m_blackTexture2D;
471  RefPtr<WebGLTexture> m_blackTextureCubeMap;
472 
473  Vector<GC3Denum> m_compressedTextureFormats;
474 
475  // Fixed-size cache of reusable image buffers for video texImage2D calls.
476  class LRUImageBufferCache {
477  public:
478  LRUImageBufferCache(int capacity);
479  // The pointer returned is owned by the image buffer map.
480  ImageBuffer* imageBuffer(const IntSize& size);
481  private:
482  void bubbleToFront(int idx);
483  std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers;
484  int m_capacity;
485  };
486  LRUImageBufferCache m_generatedImageCache;
487 
488  GC3Dint m_maxTextureSize;
489  GC3Dint m_maxCubeMapTextureSize;
490  GC3Dint m_maxRenderbufferSize;
491  GC3Dint m_maxViewportDims[2];
492  GC3Dint m_maxTextureLevel;
493  GC3Dint m_maxCubeMapTextureLevel;
494 
495  GC3Dint m_maxDrawBuffers;
496  GC3Dint m_maxColorAttachments;
497  GC3Denum m_backDrawBuffer;
498  bool m_drawBuffersWebGLRequirementsChecked;
499  bool m_drawBuffersSupported;
500 
501  GC3Dint m_packAlignment;
502  GC3Dint m_unpackAlignment;
503  bool m_unpackFlipY;
504  bool m_unpackPremultiplyAlpha;
505  GC3Denum m_unpackColorspaceConversion;
506  bool m_contextLost;
507  LostContextMode m_contextLostMode;
508  GraphicsContext3D::Attributes m_attributes;
509 
510  bool m_layerCleared;
511  GC3Dfloat m_clearColor[4];
512  bool m_scissorEnabled;
513  GC3Dfloat m_clearDepth;
514  GC3Dint m_clearStencil;
515  GC3Dboolean m_colorMask[4];
516  GC3Dboolean m_depthMask;
517 
518  bool m_stencilEnabled;
519  GC3Duint m_stencilMask, m_stencilMaskBack;
520  GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
521  GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack;
522 
523  bool m_isGLES2Compliant;
524  bool m_isGLES2NPOTStrict;
525  bool m_isErrorGeneratedOnOutOfBoundsAccesses;
526  bool m_isResourceSafe;
527  bool m_isDepthStencilSupported;
528  bool m_isRobustnessEXTSupported;
529 
530  bool m_synthesizedErrorsToConsole;
531  int m_numGLErrorsToConsoleAllowed;
532 
533  // A WebGLRenderingContext can be created in a state where it appears as
534  // a valid and active context, but will not execute any important operations
535  // until its load policy is completely resolved.
536  bool m_isPendingPolicyResolution;
537  bool m_hasRequestedPolicyResolution;
538  bool isContextLostOrPending();
539 
540  // Enabled extension objects.
541  std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic;
542  std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD;
543  std::unique_ptr<OESTextureFloat> m_oesTextureFloat;
544  std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear;
545  std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat;
546  std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear;
547  std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives;
548  std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject;
549  std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint;
550  std::unique_ptr<WebGLLoseContext> m_webglLoseContext;
551  std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo;
552  std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders;
553  std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC;
554  std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC;
555  std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC;
556  std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture;
557  std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers;
558  std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays;
559 
560  // Helpers for getParameter and others
561  WebGLGetInfo getBooleanParameter(GC3Denum);
562  WebGLGetInfo getBooleanArrayParameter(GC3Denum);
563  WebGLGetInfo getFloatParameter(GC3Denum);
564  WebGLGetInfo getIntParameter(GC3Denum);
565  WebGLGetInfo getUnsignedIntParameter(GC3Denum);
566  WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum);
567  WebGLGetInfo getWebGLIntArrayParameter(GC3Denum);
568 
569  // Clear the backbuffer if it was composited since the last operation.
570  // clearMask is set to the bitfield of any clear that would happen anyway at this time
571  // and the function returns true if that clear is now unnecessary.
572  bool clearIfComposited(GC3Dbitfield clearMask = 0);
573 
574  // Helper to restore state that clearing the framebuffer may destroy.
575  void restoreStateAfterClear();
576 
577  void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
578  void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
579  void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
580  void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
581 
582  void checkTextureCompleteness(const char*, bool);
583 
584  void createFallbackBlackTextures1x1();
585 
586  // Helper function for copyTex{Sub}Image, check whether the internalformat
587  // and the color buffer format of the current bound framebuffer combination
588  // is valid.
589  bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
590  GC3Denum colorBufferFormat);
591 
592  // Helper function to get the bound framebuffer's color buffer format.
593  GC3Denum getBoundFramebufferColorFormat();
594 
595  // Helper function to get the bound framebuffer's width.
596  int getBoundFramebufferWidth();
597 
598  // Helper function to get the bound framebuffer's height.
599  int getBoundFramebufferHeight();
600 
601  // Helper function to verify limits on the length of uniform and attribute locations.
602  bool validateLocationLength(const char* functionName, const String&);
603 
604  // Helper function to check if size is non-negative.
605  // Generate GL error and return false for negative inputs; otherwise, return true.
606  bool validateSize(const char* functionName, GC3Dint x, GC3Dint y);
607 
608  // Helper function to check if all characters in the string belong to the
609  // ASCII subset as defined in GLSL ES 1.0 spec section 3.1.
610  bool validateString(const char* functionName, const String&);
611 
612  // Helper function to check target and texture bound to the target.
613  // Generate GL errors and return 0 if target is invalid or texture bound is
614  // null. Otherwise, return the texture bound to the target.
615  WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap);
616 
617  // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
618  // Generates GL error and returns false if parameters are invalid.
619  bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
620 
621  // Helper function to check input level for functions {copy}Tex{Sub}Image.
622  // Generates GL error and returns false if level is invalid.
623  bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
624 
625  enum TexFuncValidationFunctionType {
626  NotTexSubImage2D,
627  TexSubImage2D,
628  };
629 
630  enum TexFuncValidationSourceType {
631  SourceArrayBufferView,
632  SourceImageData,
633  SourceHTMLImageElement,
634  SourceHTMLCanvasElement,
635  SourceHTMLVideoElement,
636  };
637 
638  // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid.
639  // Otherwise, it would return quickly without doing other work.
640  bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
641  GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset);
642 
643  // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
644  // Generates GL error and returns false if parameters are invalid.
645  bool validateTexFuncParameters(const char* functionName,
646  TexFuncValidationFunctionType,
647  GC3Denum target, GC3Dint level,
648  GC3Denum internalformat,
649  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
650  GC3Denum format, GC3Denum type);
651 
652  enum NullDisposition {
653  NullAllowed,
654  NullNotAllowed
655  };
656 
657  // Helper function to validate that the given ArrayBufferView
658  // is of the correct type and contains enough data for the texImage call.
659  // Generates GL error and returns false if parameters are invalid.
660  bool validateTexFuncData(const char* functionName, GC3Dint level,
661  GC3Dsizei width, GC3Dsizei height,
662  GC3Denum format, GC3Denum type,
663  ArrayBufferView* pixels,
664  NullDisposition);
665 
666  // Helper function to validate a given texture format is settable as in
667  // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
668  // copyTexSubImage2D.
669  // Generates GL error and returns false if the format is not settable.
670  bool validateSettableTexFormat(const char* functionName, GC3Denum format);
671 
672  // Helper function to validate compressed texture data is correct size
673  // for the given format and dimensions.
674  bool validateCompressedTexFuncData(const char* functionName,
675  GC3Dsizei width, GC3Dsizei height,
676  GC3Denum format, ArrayBufferView* pixels);
677 
678  // Helper function for validating compressed texture formats.
679  bool validateCompressedTexFormat(GC3Denum format);
680 
681  // Helper function to validate compressed texture dimensions are valid for
682  // the given format.
683  bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
684 
685  // Helper function to validate compressed texture dimensions are valid for
686  // the given format.
687  bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
688  GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
689 
690  // Helper function to validate mode for draw{Arrays/Elements}.
691  bool validateDrawMode(const char* functionName, GC3Denum);
692 
693  // Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
694  bool validateStencilSettings(const char* functionName);
695 
696  // Helper function to validate stencil func.
697  bool validateStencilFunc(const char* functionName, GC3Denum);
698 
699  // Helper function for texParameterf and texParameteri.
700  void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
701 
702  // Helper function to print GL errors to console.
703  void printGLErrorToConsole(const String&);
704  void printGLWarningToConsole(const char* function, const char* reason);
705 
706  // Helper function to print warnings to console. Currently
707  // used only to warn about use of obsolete functions.
708  void printWarningToConsole(const String&);
709 
710  // Helper function to validate input parameters for framebuffer functions.
711  // Generate GL error if parameters are illegal.
712  bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment);
713 
714  // Helper function to validate blend equation mode.
715  bool validateBlendEquation(const char* functionName, GC3Denum);
716 
717  // Helper function to validate blend func factors.
718  bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
719 
720  // Helper function to validate a GL capability.
721  bool validateCapability(const char* functionName, GC3Denum);
722 
723  // Helper function to validate input parameters for uniform functions.
724  bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod);
725  bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod);
726  bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod);
727  bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod);
728  bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod);
729 
730  // Helper function to validate parameters for bufferData.
731  // Return the current bound buffer to target, or 0 if parameters are invalid.
732  WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage);
733 
734  // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin.
735  bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&);
736 
737  // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin.
738  bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&);
739 
740 #if ENABLE(VIDEO)
741  // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin.
742  bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&);
743 #endif
744 
745  // Helper functions for vertexAttribNf{v}.
746  void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat);
747  void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize);
748  void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize);
749 
750  // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
751  // Return false if caller should return without further processing.
752  bool deleteObject(WebGLObject*);
753 
754  // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram.
755  // If the object has already been deleted, set deleted to true upon return.
756  // Return false if caller should return without further processing.
757  bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted);
758 
759  // Helpers for simulating vertexAttrib0
760  void initVertexAttrib0();
761  bool simulateVertexAttrib0(GC3Dsizei numVertex);
762  void restoreStatesAfterVertexAttrib0Simulation();
763 
764  void dispatchContextLostEvent();
765  // Helper for restoration after context lost.
766  void maybeRestoreContext();
767 
768  // Determine if we are running privileged code in the browser, for example,
769  // a Safari or Chrome extension.
770  bool allowPrivilegedExtensions() const;
771 
772  enum ConsoleDisplayPreference {
773  DisplayInConsole,
774  DontDisplayInConsole
775  };
776 
777  // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message
778  // to the JavaScript console.
779  void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole);
780 
781  String ensureNotNull(const String&) const;
782 
783  // Enable or disable stencil test based on user setting and
784  // whether the current FBO has a stencil buffer.
785  void applyStencilTest();
786 
787  // Helper for enabling or disabling a capability.
788  void enableOrDisable(GC3Denum capability, bool enable);
789 
790  // Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
791  IntSize clampedCanvasSize();
792 
793  // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0.
794  // Later, return the cached value.
795  GC3Dint getMaxDrawBuffers();
796  GC3Dint getMaxColorAttachments();
797 
798  void setBackDrawBuffer(GC3Denum);
799 
800  void restoreCurrentFramebuffer();
801  void restoreCurrentTexture2D();
802 
803  // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
804  bool supportsDrawBuffers();
 35 WebGL1RenderingContext(HTMLCanvasElement*, GraphicsContext3D::Attributes);
 36 WebGL1RenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes);
80537};
806 
 38
80739} // namespace WebCore
80840
80941#endif
working copy

Source/WebCore/html/canvas/WebGL1RenderingContext.idl

 1/*
 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26typedef unsigned long GLenum;
 27typedef boolean GLboolean;
 28typedef unsigned long GLbitfield;
 29typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */
 30typedef short GLshort;
 31typedef long GLint;
 32typedef long GLsizei;
 33typedef long long GLintptr;
 34typedef long long GLsizeiptr;
 35typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */
 36typedef unsigned short GLushort;
 37typedef unsigned long GLuint;
 38typedef unrestricted float GLfloat;
 39typedef unrestricted float GLclampf;
 40
 41[
 42 Conditional=WEBGL,
 43 JSCustomMarkFunction,
 44 DoNotCheckConstants,
 45] interface WebGLRenderingContext : CanvasRenderingContext {
 46
 47 /* ClearBufferMask */
 48 const GLenum DEPTH_BUFFER_BIT = 0x00000100;
 49 const GLenum STENCIL_BUFFER_BIT = 0x00000400;
 50 const GLenum COLOR_BUFFER_BIT = 0x00004000;
 51
 52 /* BeginMode */
 53 const GLenum POINTS = 0x0000;
 54 const GLenum LINES = 0x0001;
 55 const GLenum LINE_LOOP = 0x0002;
 56 const GLenum LINE_STRIP = 0x0003;
 57 const GLenum TRIANGLES = 0x0004;
 58 const GLenum TRIANGLE_STRIP = 0x0005;
 59 const GLenum TRIANGLE_FAN = 0x0006;
 60
 61 /* AlphaFunction (not supported in ES20) */
 62 /* NEVER */
 63 /* LESS */
 64 /* EQUAL */
 65 /* LEQUAL */
 66 /* GREATER */
 67 /* NOTEQUAL */
 68 /* GEQUAL */
 69 /* ALWAYS */
 70
 71 /* BlendingFactorDest */
 72 const GLenum ZERO = 0;
 73 const GLenum ONE = 1;
 74 const GLenum SRC_COLOR = 0x0300;
 75 const GLenum ONE_MINUS_SRC_COLOR = 0x0301;
 76 const GLenum SRC_ALPHA = 0x0302;
 77 const GLenum ONE_MINUS_SRC_ALPHA = 0x0303;
 78 const GLenum DST_ALPHA = 0x0304;
 79 const GLenum ONE_MINUS_DST_ALPHA = 0x0305;
 80
 81 /* BlendingFactorSrc */
 82 /* ZERO */
 83 /* ONE */
 84 const GLenum DST_COLOR = 0x0306;
 85 const GLenum ONE_MINUS_DST_COLOR = 0x0307;
 86 const GLenum SRC_ALPHA_SATURATE = 0x0308;
 87 /* SRC_ALPHA */
 88 /* ONE_MINUS_SRC_ALPHA */
 89 /* DST_ALPHA */
 90 /* ONE_MINUS_DST_ALPHA */
 91
 92 /* BlendEquationSeparate */
 93 const GLenum FUNC_ADD = 0x8006;
 94 const GLenum BLEND_EQUATION = 0x8009;
 95 const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */
 96 const GLenum BLEND_EQUATION_ALPHA = 0x883D;
 97
 98 /* BlendSubtract */
 99 const GLenum FUNC_SUBTRACT = 0x800A;
 100 const GLenum FUNC_REVERSE_SUBTRACT = 0x800B;
 101
 102 /* Separate Blend Functions */
 103 const GLenum BLEND_DST_RGB = 0x80C8;
 104 const GLenum BLEND_SRC_RGB = 0x80C9;
 105 const GLenum BLEND_DST_ALPHA = 0x80CA;
 106 const GLenum BLEND_SRC_ALPHA = 0x80CB;
 107 const GLenum CONSTANT_COLOR = 0x8001;
 108 const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002;
 109 const GLenum CONSTANT_ALPHA = 0x8003;
 110 const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004;
 111 const GLenum BLEND_COLOR = 0x8005;
 112
 113 /* Buffer Objects */
 114 const GLenum ARRAY_BUFFER = 0x8892;
 115 const GLenum ELEMENT_ARRAY_BUFFER = 0x8893;
 116 const GLenum ARRAY_BUFFER_BINDING = 0x8894;
 117 const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
 118
 119 const GLenum STREAM_DRAW = 0x88E0;
 120 const GLenum STATIC_DRAW = 0x88E4;
 121 const GLenum DYNAMIC_DRAW = 0x88E8;
 122
 123 const GLenum BUFFER_SIZE = 0x8764;
 124 const GLenum BUFFER_USAGE = 0x8765;
 125
 126 const GLenum CURRENT_VERTEX_ATTRIB = 0x8626;
 127
 128 /* CullFaceMode */
 129 const GLenum FRONT = 0x0404;
 130 const GLenum BACK = 0x0405;
 131 const GLenum FRONT_AND_BACK = 0x0408;
 132
 133 /* DepthFunction */
 134 /* NEVER */
 135 /* LESS */
 136 /* EQUAL */
 137 /* LEQUAL */
 138 /* GREATER */
 139 /* NOTEQUAL */
 140 /* GEQUAL */
 141 /* ALWAYS */
 142
 143 /* EnableCap */
 144 const GLenum TEXTURE_2D = 0x0DE1;
 145 const GLenum CULL_FACE = 0x0B44;
 146 const GLenum BLEND = 0x0BE2;
 147 const GLenum DITHER = 0x0BD0;
 148 const GLenum STENCIL_TEST = 0x0B90;
 149 const GLenum DEPTH_TEST = 0x0B71;
 150 const GLenum SCISSOR_TEST = 0x0C11;
 151 const GLenum POLYGON_OFFSET_FILL = 0x8037;
 152 const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
 153 const GLenum SAMPLE_COVERAGE = 0x80A0;
 154
 155 /* ErrorCode */
 156 const GLenum NO_ERROR = 0;
 157 const GLenum INVALID_ENUM = 0x0500;
 158 const GLenum INVALID_VALUE = 0x0501;
 159 const GLenum INVALID_OPERATION = 0x0502;
 160 const GLenum OUT_OF_MEMORY = 0x0505;
 161
 162 /* FrontFaceDirection */
 163 const GLenum CW = 0x0900;
 164 const GLenum CCW = 0x0901;
 165
 166 /* GetPName */
 167 const GLenum LINE_WIDTH = 0x0B21;
 168 const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D;
 169 const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E;
 170 const GLenum CULL_FACE_MODE = 0x0B45;
 171 const GLenum FRONT_FACE = 0x0B46;
 172 const GLenum DEPTH_RANGE = 0x0B70;
 173 const GLenum DEPTH_WRITEMASK = 0x0B72;
 174 const GLenum DEPTH_CLEAR_VALUE = 0x0B73;
 175 const GLenum DEPTH_FUNC = 0x0B74;
 176 const GLenum STENCIL_CLEAR_VALUE = 0x0B91;
 177 const GLenum STENCIL_FUNC = 0x0B92;
 178 const GLenum STENCIL_FAIL = 0x0B94;
 179 const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95;
 180 const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96;
 181 const GLenum STENCIL_REF = 0x0B97;
 182 const GLenum STENCIL_VALUE_MASK = 0x0B93;
 183 const GLenum STENCIL_WRITEMASK = 0x0B98;
 184 const GLenum STENCIL_BACK_FUNC = 0x8800;
 185 const GLenum STENCIL_BACK_FAIL = 0x8801;
 186 const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
 187 const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
 188 const GLenum STENCIL_BACK_REF = 0x8CA3;
 189 const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4;
 190 const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5;
 191 const GLenum VIEWPORT = 0x0BA2;
 192 const GLenum SCISSOR_BOX = 0x0C10;
 193 /* SCISSOR_TEST */
 194 const GLenum COLOR_CLEAR_VALUE = 0x0C22;
 195 const GLenum COLOR_WRITEMASK = 0x0C23;
 196 const GLenum UNPACK_ALIGNMENT = 0x0CF5;
 197 const GLenum PACK_ALIGNMENT = 0x0D05;
 198 const GLenum MAX_TEXTURE_SIZE = 0x0D33;
 199 const GLenum MAX_VIEWPORT_DIMS = 0x0D3A;
 200 const GLenum SUBPIXEL_BITS = 0x0D50;
 201 const GLenum RED_BITS = 0x0D52;
 202 const GLenum GREEN_BITS = 0x0D53;
 203 const GLenum BLUE_BITS = 0x0D54;
 204 const GLenum ALPHA_BITS = 0x0D55;
 205 const GLenum DEPTH_BITS = 0x0D56;
 206 const GLenum STENCIL_BITS = 0x0D57;
 207 const GLenum POLYGON_OFFSET_UNITS = 0x2A00;
 208 /* POLYGON_OFFSET_FILL */
 209 const GLenum POLYGON_OFFSET_FACTOR = 0x8038;
 210 const GLenum TEXTURE_BINDING_2D = 0x8069;
 211 const GLenum SAMPLE_BUFFERS = 0x80A8;
 212 const GLenum SAMPLES = 0x80A9;
 213 const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA;
 214 const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB;
 215
 216 /* GetTextureParameter */
 217 /* TEXTURE_MAG_FILTER */
 218 /* TEXTURE_MIN_FILTER */
 219 /* TEXTURE_WRAP_S */
 220 /* TEXTURE_WRAP_T */
 221
 222 const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3;
 223
 224 /* HintMode */
 225 const GLenum DONT_CARE = 0x1100;
 226 const GLenum FASTEST = 0x1101;
 227 const GLenum NICEST = 0x1102;
 228
 229 /* HintTarget */
 230 const GLenum GENERATE_MIPMAP_HINT = 0x8192;
 231
 232 /* DataType */
 233 const GLenum BYTE = 0x1400;
 234 const GLenum UNSIGNED_BYTE = 0x1401;
 235 const GLenum SHORT = 0x1402;
 236 const GLenum UNSIGNED_SHORT = 0x1403;
 237 const GLenum INT = 0x1404;
 238 const GLenum UNSIGNED_INT = 0x1405;
 239 const GLenum FLOAT = 0x1406;
 240
 241 /* PixelFormat */
 242 const GLenum DEPTH_COMPONENT = 0x1902;
 243 const GLenum ALPHA = 0x1906;
 244 const GLenum RGB = 0x1907;
 245 const GLenum RGBA = 0x1908;
 246 const GLenum LUMINANCE = 0x1909;
 247 const GLenum LUMINANCE_ALPHA = 0x190A;
 248
 249 /* PixelType */
 250 /* UNSIGNED_BYTE */
 251 const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033;
 252 const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034;
 253 const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363;
 254
 255 /* Shaders */
 256 const GLenum FRAGMENT_SHADER = 0x8B30;
 257 const GLenum VERTEX_SHADER = 0x8B31;
 258 const GLenum MAX_VERTEX_ATTRIBS = 0x8869;
 259 const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
 260 const GLenum MAX_VARYING_VECTORS = 0x8DFC;
 261 const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
 262 const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
 263 const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872;
 264 const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
 265 const GLenum SHADER_TYPE = 0x8B4F;
 266 const GLenum DELETE_STATUS = 0x8B80;
 267 const GLenum LINK_STATUS = 0x8B82;
 268 const GLenum VALIDATE_STATUS = 0x8B83;
 269 const GLenum ATTACHED_SHADERS = 0x8B85;
 270 const GLenum ACTIVE_UNIFORMS = 0x8B86;
 271 const GLenum ACTIVE_ATTRIBUTES = 0x8B89;
 272 const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C;
 273 const GLenum CURRENT_PROGRAM = 0x8B8D;
 274
 275 /* StencilFunction */
 276 const GLenum NEVER = 0x0200;
 277 const GLenum LESS = 0x0201;
 278 const GLenum EQUAL = 0x0202;
 279 const GLenum LEQUAL = 0x0203;
 280 const GLenum GREATER = 0x0204;
 281 const GLenum NOTEQUAL = 0x0205;
 282 const GLenum GEQUAL = 0x0206;
 283 const GLenum ALWAYS = 0x0207;
 284
 285 /* StencilOp */
 286 /* ZERO */
 287 const GLenum KEEP = 0x1E00;
 288 const GLenum REPLACE = 0x1E01;
 289 const GLenum INCR = 0x1E02;
 290 const GLenum DECR = 0x1E03;
 291 const GLenum INVERT = 0x150A;
 292 const GLenum INCR_WRAP = 0x8507;
 293 const GLenum DECR_WRAP = 0x8508;
 294
 295 /* StringName */
 296 const GLenum VENDOR = 0x1F00;
 297 const GLenum RENDERER = 0x1F01;
 298 const GLenum VERSION = 0x1F02;
 299
 300 /* TextureMagFilter */
 301 const GLenum NEAREST = 0x2600;
 302 const GLenum LINEAR = 0x2601;
 303
 304 /* TextureMinFilter */
 305 /* NEAREST */
 306 /* LINEAR */
 307 const GLenum NEAREST_MIPMAP_NEAREST = 0x2700;
 308 const GLenum LINEAR_MIPMAP_NEAREST = 0x2701;
 309 const GLenum NEAREST_MIPMAP_LINEAR = 0x2702;
 310 const GLenum LINEAR_MIPMAP_LINEAR = 0x2703;
 311
 312 /* TextureParameterName */
 313 const GLenum TEXTURE_MAG_FILTER = 0x2800;
 314 const GLenum TEXTURE_MIN_FILTER = 0x2801;
 315 const GLenum TEXTURE_WRAP_S = 0x2802;
 316 const GLenum TEXTURE_WRAP_T = 0x2803;
 317
 318 /* TextureTarget */
 319 /* TEXTURE_2D */
 320 const GLenum TEXTURE = 0x1702;
 321
 322 const GLenum TEXTURE_CUBE_MAP = 0x8513;
 323 const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514;
 324 const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
 325 const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
 326 const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
 327 const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
 328 const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
 329 const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
 330 const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
 331
 332 /* TextureUnit */
 333 const GLenum TEXTURE0 = 0x84C0;
 334 const GLenum TEXTURE1 = 0x84C1;
 335 const GLenum TEXTURE2 = 0x84C2;
 336 const GLenum TEXTURE3 = 0x84C3;
 337 const GLenum TEXTURE4 = 0x84C4;
 338 const GLenum TEXTURE5 = 0x84C5;
 339 const GLenum TEXTURE6 = 0x84C6;
 340 const GLenum TEXTURE7 = 0x84C7;
 341 const GLenum TEXTURE8 = 0x84C8;
 342 const GLenum TEXTURE9 = 0x84C9;
 343 const GLenum TEXTURE10 = 0x84CA;
 344 const GLenum TEXTURE11 = 0x84CB;
 345 const GLenum TEXTURE12 = 0x84CC;
 346 const GLenum TEXTURE13 = 0x84CD;
 347 const GLenum TEXTURE14 = 0x84CE;
 348 const GLenum TEXTURE15 = 0x84CF;
 349 const GLenum TEXTURE16 = 0x84D0;
 350 const GLenum TEXTURE17 = 0x84D1;
 351 const GLenum TEXTURE18 = 0x84D2;
 352 const GLenum TEXTURE19 = 0x84D3;
 353 const GLenum TEXTURE20 = 0x84D4;
 354 const GLenum TEXTURE21 = 0x84D5;
 355 const GLenum TEXTURE22 = 0x84D6;
 356 const GLenum TEXTURE23 = 0x84D7;
 357 const GLenum TEXTURE24 = 0x84D8;
 358 const GLenum TEXTURE25 = 0x84D9;
 359 const GLenum TEXTURE26 = 0x84DA;
 360 const GLenum TEXTURE27 = 0x84DB;
 361 const GLenum TEXTURE28 = 0x84DC;
 362 const GLenum TEXTURE29 = 0x84DD;
 363 const GLenum TEXTURE30 = 0x84DE;
 364 const GLenum TEXTURE31 = 0x84DF;
 365 const GLenum ACTIVE_TEXTURE = 0x84E0;
 366
 367 /* TextureWrapMode */
 368 const GLenum REPEAT = 0x2901;
 369 const GLenum CLAMP_TO_EDGE = 0x812F;
 370 const GLenum MIRRORED_REPEAT = 0x8370;
 371
 372 /* Uniform Types */
 373 const GLenum FLOAT_VEC2 = 0x8B50;
 374 const GLenum FLOAT_VEC3 = 0x8B51;
 375 const GLenum FLOAT_VEC4 = 0x8B52;
 376 const GLenum INT_VEC2 = 0x8B53;
 377 const GLenum INT_VEC3 = 0x8B54;
 378 const GLenum INT_VEC4 = 0x8B55;
 379 const GLenum BOOL = 0x8B56;
 380 const GLenum BOOL_VEC2 = 0x8B57;
 381 const GLenum BOOL_VEC3 = 0x8B58;
 382 const GLenum BOOL_VEC4 = 0x8B59;
 383 const GLenum FLOAT_MAT2 = 0x8B5A;
 384 const GLenum FLOAT_MAT3 = 0x8B5B;
 385 const GLenum FLOAT_MAT4 = 0x8B5C;
 386 const GLenum SAMPLER_2D = 0x8B5E;
 387 const GLenum SAMPLER_CUBE = 0x8B60;
 388
 389 /* Vertex Arrays */
 390 const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
 391 const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
 392 const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
 393 const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
 394 const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
 395 const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
 396 const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
 397
 398 /* Shader Source */
 399 const GLenum COMPILE_STATUS = 0x8B81;
 400
 401 /* Shader Precision-Specified Types */
 402 const GLenum LOW_FLOAT = 0x8DF0;
 403 const GLenum MEDIUM_FLOAT = 0x8DF1;
 404 const GLenum HIGH_FLOAT = 0x8DF2;
 405 const GLenum LOW_INT = 0x8DF3;
 406 const GLenum MEDIUM_INT = 0x8DF4;
 407 const GLenum HIGH_INT = 0x8DF5;
 408
 409 /* Framebuffer Object. */
 410 const GLenum FRAMEBUFFER = 0x8D40;
 411 const GLenum RENDERBUFFER = 0x8D41;
 412
 413 const GLenum RGBA4 = 0x8056;
 414 const GLenum RGB5_A1 = 0x8057;
 415 const GLenum RGB565 = 0x8D62;
 416 const GLenum DEPTH_COMPONENT16 = 0x81A5;
 417 const GLenum STENCIL_INDEX = 0x1901;
 418 const GLenum STENCIL_INDEX8 = 0x8D48;
 419 const GLenum DEPTH_STENCIL = 0x84F9;
 420
 421 const GLenum SRGB_EXT = 0x8C40;
 422 const GLenum SRGB_ALPHA_EXT = 0x8C42;
 423 const GLenum SRGB8_ALPHA8_EXT = 0x8C43;
 424 const GLenum FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT = 0x8210;
 425
 426 const GLenum MIN_EXT = 0x8007;
 427 const GLenum MAX_EXT = 0x8008;
 428
 429 const GLenum RENDERBUFFER_WIDTH = 0x8D42;
 430 const GLenum RENDERBUFFER_HEIGHT = 0x8D43;
 431 const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
 432 const GLenum RENDERBUFFER_RED_SIZE = 0x8D50;
 433 const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51;
 434 const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52;
 435 const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53;
 436 const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54;
 437 const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55;
 438
 439 const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
 440 const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
 441 const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
 442 const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
 443
 444 const GLenum COLOR_ATTACHMENT0 = 0x8CE0;
 445 const GLenum DEPTH_ATTACHMENT = 0x8D00;
 446 const GLenum STENCIL_ATTACHMENT = 0x8D20;
 447 const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A;
 448
 449 const GLenum NONE = 0;
 450
 451 const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5;
 452 const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
 453 const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
 454 const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
 455 const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
 456
 457 const GLenum FRAMEBUFFER_BINDING = 0x8CA6;
 458 const GLenum RENDERBUFFER_BINDING = 0x8CA7;
 459 const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8;
 460
 461 const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506;
 462
 463 /* WebGL-specific enums */
 464 const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240;
 465 const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
 466 const GLenum CONTEXT_LOST_WEBGL = 0x9242;
 467 const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
 468 const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
 469
 470 readonly attribute GLsizei drawingBufferWidth;
 471 readonly attribute GLsizei drawingBufferHeight;
 472
 473 [StrictTypeChecking, RaisesException] void activeTexture(GLenum texture);
 474 [StrictTypeChecking, RaisesException] void attachShader(WebGLProgram program, WebGLShader shader);
 475 [StrictTypeChecking, RaisesException] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name);
 476 [StrictTypeChecking, RaisesException] void bindBuffer(GLenum target, WebGLBuffer buffer);
 477 [StrictTypeChecking, RaisesException] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer);
 478 [StrictTypeChecking, RaisesException] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer);
 479 [StrictTypeChecking, RaisesException] void bindTexture(GLenum target, WebGLTexture texture);
 480 [StrictTypeChecking] void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 481 [StrictTypeChecking] void blendEquation(GLenum mode);
 482 [StrictTypeChecking] void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
 483 [StrictTypeChecking] void blendFunc(GLenum sfactor, GLenum dfactor);
 484 [StrictTypeChecking] void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
 485 [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
 486 [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage);
 487 [StrictTypeChecking, RaisesException] void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
 488 [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data);
 489 [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView? data);
 490
 491 [StrictTypeChecking] GLenum checkFramebufferStatus(GLenum target);
 492 [StrictTypeChecking] void clear(GLbitfield mask);
 493 [StrictTypeChecking] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 494 [StrictTypeChecking] void clearDepth(GLclampf depth);
 495 [StrictTypeChecking] void clearStencil(GLint s);
 496 [StrictTypeChecking] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 497 [StrictTypeChecking, RaisesException] void compileShader(WebGLShader shader);
 498
 499 [StrictTypeChecking] void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
 500 GLsizei width, GLsizei height, GLint border, ArrayBufferView data);
 501 [StrictTypeChecking] void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 502 GLsizei width, GLsizei height, GLenum format, ArrayBufferView data);
 503
 504 [StrictTypeChecking] void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
 505 [StrictTypeChecking] void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 506
 507 [StrictTypeChecking] WebGLBuffer createBuffer();
 508 [StrictTypeChecking] WebGLFramebuffer createFramebuffer();
 509 [StrictTypeChecking] WebGLProgram createProgram();
 510 [StrictTypeChecking] WebGLRenderbuffer createRenderbuffer();
 511 [StrictTypeChecking, RaisesException] WebGLShader createShader(GLenum type);
 512 [StrictTypeChecking] WebGLTexture createTexture();
 513
 514 [StrictTypeChecking] void cullFace(GLenum mode);
 515
 516 [StrictTypeChecking] void deleteBuffer(WebGLBuffer buffer);
 517 [StrictTypeChecking] void deleteFramebuffer(WebGLFramebuffer framebuffer);
 518 [StrictTypeChecking] void deleteProgram(WebGLProgram program);
 519 [StrictTypeChecking] void deleteRenderbuffer(WebGLRenderbuffer renderbuffer);
 520 [StrictTypeChecking] void deleteShader(WebGLShader shader);
 521 [StrictTypeChecking] void deleteTexture(WebGLTexture texture);
 522
 523 [StrictTypeChecking] void depthFunc(GLenum func);
 524 [StrictTypeChecking] void depthMask(GLboolean flag);
 525 [StrictTypeChecking] void depthRange(GLclampf zNear, GLclampf zFar);
 526 [StrictTypeChecking, RaisesException] void detachShader(WebGLProgram program, WebGLShader shader);
 527 [StrictTypeChecking] void disable(GLenum cap);
 528 [StrictTypeChecking, RaisesException] void disableVertexAttribArray(GLuint index);
 529 [StrictTypeChecking, RaisesException] void drawArrays(GLenum mode, GLint first, GLsizei count);
 530 [StrictTypeChecking, RaisesException] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset);
 531
 532 [StrictTypeChecking] void enable(GLenum cap);
 533 [StrictTypeChecking, RaisesException] void enableVertexAttribArray(GLuint index);
 534 [StrictTypeChecking] void finish();
 535 [StrictTypeChecking] void flush();
 536 [StrictTypeChecking, RaisesException] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer);
 537 [StrictTypeChecking, RaisesException] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level);
 538 [StrictTypeChecking] void frontFace(GLenum mode);
 539 [StrictTypeChecking] void generateMipmap(GLenum target);
 540
 541 [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index);
 542 [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index);
 543
 544 [StrictTypeChecking, Custom, RaisesException] void getAttachedShaders(WebGLProgram program);
 545
 546 [StrictTypeChecking] GLint getAttribLocation(WebGLProgram program, DOMString name);
 547
 548 [StrictTypeChecking, Custom] any getBufferParameter(GLenum target, GLenum pname);
 549
 550 [StrictTypeChecking] WebGLContextAttributes getContextAttributes();
 551
 552 [StrictTypeChecking] GLenum getError();
 553
 554 // object getExtension(DOMString name);
 555 [StrictTypeChecking, Custom] any getExtension(DOMString name);
 556
 557 [StrictTypeChecking, Custom, RaisesException] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname);
 558 [StrictTypeChecking, Custom, RaisesException] any getParameter(GLenum pname);
 559 [StrictTypeChecking, Custom, RaisesException] any getProgramParameter(WebGLProgram program, GLenum pname);
 560 [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getProgramInfoLog(WebGLProgram program);
 561 [StrictTypeChecking, Custom, RaisesException] any getRenderbufferParameter(GLenum target, GLenum pname);
 562 [StrictTypeChecking, Custom, RaisesException] any getShaderParameter(WebGLShader shader, GLenum pname);
 563
 564 [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderInfoLog(WebGLShader shader);
 565
 566 [StrictTypeChecking, RaisesException] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
 567
 568 [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderSource(WebGLShader shader);
 569
 570 [StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions();
 571
 572 [StrictTypeChecking, Custom, RaisesException] any getTexParameter(GLenum target, GLenum pname);
 573
 574 [StrictTypeChecking, Custom, RaisesException] any getUniform(WebGLProgram program, WebGLUniformLocation location);
 575
 576 [StrictTypeChecking, RaisesException] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name);
 577
 578 [StrictTypeChecking, Custom, RaisesException] any getVertexAttrib(GLuint index, GLenum pname);
 579
 580 [StrictTypeChecking] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
 581
 582 [StrictTypeChecking] void hint(GLenum target, GLenum mode);
 583 [StrictTypeChecking] GLboolean isBuffer(WebGLBuffer buffer);
 584 [StrictTypeChecking] GLboolean isContextLost();
 585 [StrictTypeChecking] GLboolean isEnabled(GLenum cap);
 586 [StrictTypeChecking] GLboolean isFramebuffer(WebGLFramebuffer framebuffer);
 587 [StrictTypeChecking] GLboolean isProgram(WebGLProgram program);
 588 [StrictTypeChecking] GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer);
 589 [StrictTypeChecking] GLboolean isShader(WebGLShader shader);
 590 [StrictTypeChecking] GLboolean isTexture(WebGLTexture texture);
 591 [StrictTypeChecking] void lineWidth(GLfloat width);
 592 [StrictTypeChecking, RaisesException] void linkProgram(WebGLProgram program);
 593 [StrictTypeChecking] void pixelStorei(GLenum pname, GLint param);
 594 [StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units);
 595
 596 [StrictTypeChecking, RaisesException] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels);
 597
 598 [StrictTypeChecking] void releaseShaderCompiler();
 599 [StrictTypeChecking] void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
 600 [StrictTypeChecking] void sampleCoverage(GLclampf value, GLboolean invert);
 601 [StrictTypeChecking] void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
 602 [StrictTypeChecking, RaisesException] void shaderSource(WebGLShader shader, DOMString string);
 603 [StrictTypeChecking] void stencilFunc(GLenum func, GLint ref, GLuint mask);
 604 [StrictTypeChecking] void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
 605 [StrictTypeChecking] void stencilMask(GLuint mask);
 606 [StrictTypeChecking] void stencilMaskSeparate(GLenum face, GLuint mask);
 607 [StrictTypeChecking] void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
 608 [StrictTypeChecking] void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
 609
 610 [StrictTypeChecking] void texParameterf(GLenum target, GLenum pname, GLfloat param);
 611 [StrictTypeChecking] void texParameteri(GLenum target, GLenum pname, GLint param);
 612
 613 // Supported forms:
 614 [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
 615 GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
 616 [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 617 GLenum format, GLenum type, ImageData? pixels);
 618 [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 619 GLenum format, GLenum type, HTMLImageElement? image);
 620 [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 621 GLenum format, GLenum type, HTMLCanvasElement? canvas);
 622#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
 623 [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 624 GLenum format, GLenum type, HTMLVideoElement? video);
 625#endif
 626
 627 [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 628 GLsizei width, GLsizei height,
 629 GLenum format, GLenum type, ArrayBufferView? pixels);
 630 [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 631 GLenum format, GLenum type, ImageData? pixels);
 632 [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 633 GLenum format, GLenum type, HTMLImageElement? image);
 634 [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 635 GLenum format, GLenum type, HTMLCanvasElement? canvas);
 636#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
 637 [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 638 GLenum format, GLenum type, HTMLVideoElement? video);
 639#endif
 640
 641 [StrictTypeChecking, RaisesException] void uniform1f(WebGLUniformLocation location, GLfloat x);
 642 [StrictTypeChecking, Custom, RaisesException] void uniform1fv(WebGLUniformLocation location, Float32Array v);
 643 [StrictTypeChecking, RaisesException] void uniform1i(WebGLUniformLocation location, GLint x);
 644 [StrictTypeChecking, Custom, RaisesException] void uniform1iv(WebGLUniformLocation location, Int32Array v);
 645 [StrictTypeChecking, RaisesException] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y);
 646 [StrictTypeChecking, Custom, RaisesException] void uniform2fv(WebGLUniformLocation location, Float32Array v);
 647 [StrictTypeChecking, RaisesException] void uniform2i(WebGLUniformLocation location, GLint x, GLint y);
 648 [StrictTypeChecking, Custom, RaisesException] void uniform2iv(WebGLUniformLocation location, Int32Array v);
 649 [StrictTypeChecking, RaisesException] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z);
 650 [StrictTypeChecking, Custom, RaisesException] void uniform3fv(WebGLUniformLocation location, Float32Array v);
 651 [StrictTypeChecking, RaisesException] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z);
 652 [StrictTypeChecking, Custom, RaisesException] void uniform3iv(WebGLUniformLocation location, Int32Array v);
 653 [StrictTypeChecking, RaisesException] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 654 [StrictTypeChecking, Custom, RaisesException] void uniform4fv(WebGLUniformLocation location, Float32Array v);
 655 [StrictTypeChecking, RaisesException] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w);
 656 [StrictTypeChecking, Custom, RaisesException] void uniform4iv(WebGLUniformLocation location, Int32Array v);
 657
 658 [StrictTypeChecking, Custom, RaisesException] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
 659 [StrictTypeChecking, Custom, RaisesException] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
 660 [StrictTypeChecking, Custom, RaisesException] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
 661
 662 [StrictTypeChecking, RaisesException] void useProgram(WebGLProgram program);
 663 [StrictTypeChecking, RaisesException] void validateProgram(WebGLProgram program);
 664
 665 [StrictTypeChecking] void vertexAttrib1f(GLuint indx, GLfloat x);
 666 [StrictTypeChecking, Custom] void vertexAttrib1fv(GLuint indx, Float32Array values);
 667 [StrictTypeChecking] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
 668 [StrictTypeChecking, Custom] void vertexAttrib2fv(GLuint indx, Float32Array values);
 669 [StrictTypeChecking] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
 670 [StrictTypeChecking, Custom] void vertexAttrib3fv(GLuint indx, Float32Array values);
 671 [StrictTypeChecking] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 672 [StrictTypeChecking, Custom] void vertexAttrib4fv(GLuint indx, Float32Array values);
 673 [StrictTypeChecking, RaisesException] void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized,
 674 GLsizei stride, GLintptr offset);
 675
 676 [StrictTypeChecking] void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 677};
176994

Source/WebCore/html/canvas/WebGL1RenderingContext.idl

11/*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
26 typedef unsigned long GLenum;
27 typedef boolean GLboolean;
28 typedef unsigned long GLbitfield;
29 typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */
30 typedef short GLshort;
31 typedef long GLint;
32 typedef long GLsizei;
33 typedef long long GLintptr;
34 typedef long long GLsizeiptr;
35 typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */
36 typedef unsigned short GLushort;
37 typedef unsigned long GLuint;
38 typedef unrestricted float GLfloat;
39 typedef unrestricted float GLclampf;
40 
4126[
4227 Conditional=WEBGL,
4328 JSCustomMarkFunction,
4429 DoNotCheckConstants,
45 ] interface WebGLRenderingContext : CanvasRenderingContext {
46 
47  /* ClearBufferMask */
48  const GLenum DEPTH_BUFFER_BIT = 0x00000100;
49  const GLenum STENCIL_BUFFER_BIT = 0x00000400;
50  const GLenum COLOR_BUFFER_BIT = 0x00004000;
51 
52  /* BeginMode */
53  const GLenum POINTS = 0x0000;
54  const GLenum LINES = 0x0001;
55  const GLenum LINE_LOOP = 0x0002;
56  const GLenum LINE_STRIP = 0x0003;
57  const GLenum TRIANGLES = 0x0004;
58  const GLenum TRIANGLE_STRIP = 0x0005;
59  const GLenum TRIANGLE_FAN = 0x0006;
60 
61  /* AlphaFunction (not supported in ES20) */
62  /* NEVER */
63  /* LESS */
64  /* EQUAL */
65  /* LEQUAL */
66  /* GREATER */
67  /* NOTEQUAL */
68  /* GEQUAL */
69  /* ALWAYS */
70 
71  /* BlendingFactorDest */
72  const GLenum ZERO = 0;
73  const GLenum ONE = 1;
74  const GLenum SRC_COLOR = 0x0300;
75  const GLenum ONE_MINUS_SRC_COLOR = 0x0301;
76  const GLenum SRC_ALPHA = 0x0302;
77  const GLenum ONE_MINUS_SRC_ALPHA = 0x0303;
78  const GLenum DST_ALPHA = 0x0304;
79  const GLenum ONE_MINUS_DST_ALPHA = 0x0305;
80 
81  /* BlendingFactorSrc */
82  /* ZERO */
83  /* ONE */
84  const GLenum DST_COLOR = 0x0306;
85  const GLenum ONE_MINUS_DST_COLOR = 0x0307;
86  const GLenum SRC_ALPHA_SATURATE = 0x0308;
87  /* SRC_ALPHA */
88  /* ONE_MINUS_SRC_ALPHA */
89  /* DST_ALPHA */
90  /* ONE_MINUS_DST_ALPHA */
91 
92  /* BlendEquationSeparate */
93  const GLenum FUNC_ADD = 0x8006;
94  const GLenum BLEND_EQUATION = 0x8009;
95  const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */
96  const GLenum BLEND_EQUATION_ALPHA = 0x883D;
97 
98  /* BlendSubtract */
99  const GLenum FUNC_SUBTRACT = 0x800A;
100  const GLenum FUNC_REVERSE_SUBTRACT = 0x800B;
101 
102  /* Separate Blend Functions */
103  const GLenum BLEND_DST_RGB = 0x80C8;
104  const GLenum BLEND_SRC_RGB = 0x80C9;
105  const GLenum BLEND_DST_ALPHA = 0x80CA;
106  const GLenum BLEND_SRC_ALPHA = 0x80CB;
107  const GLenum CONSTANT_COLOR = 0x8001;
108  const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002;
109  const GLenum CONSTANT_ALPHA = 0x8003;
110  const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004;
111  const GLenum BLEND_COLOR = 0x8005;
112 
113  /* Buffer Objects */
114  const GLenum ARRAY_BUFFER = 0x8892;
115  const GLenum ELEMENT_ARRAY_BUFFER = 0x8893;
116  const GLenum ARRAY_BUFFER_BINDING = 0x8894;
117  const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
118 
119  const GLenum STREAM_DRAW = 0x88E0;
120  const GLenum STATIC_DRAW = 0x88E4;
121  const GLenum DYNAMIC_DRAW = 0x88E8;
122 
123  const GLenum BUFFER_SIZE = 0x8764;
124  const GLenum BUFFER_USAGE = 0x8765;
125 
126  const GLenum CURRENT_VERTEX_ATTRIB = 0x8626;
127 
128  /* CullFaceMode */
129  const GLenum FRONT = 0x0404;
130  const GLenum BACK = 0x0405;
131  const GLenum FRONT_AND_BACK = 0x0408;
132 
133  /* DepthFunction */
134  /* NEVER */
135  /* LESS */
136  /* EQUAL */
137  /* LEQUAL */
138  /* GREATER */
139  /* NOTEQUAL */
140  /* GEQUAL */
141  /* ALWAYS */
142 
143  /* EnableCap */
144  const GLenum TEXTURE_2D = 0x0DE1;
145  const GLenum CULL_FACE = 0x0B44;
146  const GLenum BLEND = 0x0BE2;
147  const GLenum DITHER = 0x0BD0;
148  const GLenum STENCIL_TEST = 0x0B90;
149  const GLenum DEPTH_TEST = 0x0B71;
150  const GLenum SCISSOR_TEST = 0x0C11;
151  const GLenum POLYGON_OFFSET_FILL = 0x8037;
152  const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
153  const GLenum SAMPLE_COVERAGE = 0x80A0;
154 
155  /* ErrorCode */
156  const GLenum NO_ERROR = 0;
157  const GLenum INVALID_ENUM = 0x0500;
158  const GLenum INVALID_VALUE = 0x0501;
159  const GLenum INVALID_OPERATION = 0x0502;
160  const GLenum OUT_OF_MEMORY = 0x0505;
161 
162  /* FrontFaceDirection */
163  const GLenum CW = 0x0900;
164  const GLenum CCW = 0x0901;
165 
166  /* GetPName */
167  const GLenum LINE_WIDTH = 0x0B21;
168  const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D;
169  const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E;
170  const GLenum CULL_FACE_MODE = 0x0B45;
171  const GLenum FRONT_FACE = 0x0B46;
172  const GLenum DEPTH_RANGE = 0x0B70;
173  const GLenum DEPTH_WRITEMASK = 0x0B72;
174  const GLenum DEPTH_CLEAR_VALUE = 0x0B73;
175  const GLenum DEPTH_FUNC = 0x0B74;
176  const GLenum STENCIL_CLEAR_VALUE = 0x0B91;
177  const GLenum STENCIL_FUNC = 0x0B92;
178  const GLenum STENCIL_FAIL = 0x0B94;
179  const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95;
180  const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96;
181  const GLenum STENCIL_REF = 0x0B97;
182  const GLenum STENCIL_VALUE_MASK = 0x0B93;
183  const GLenum STENCIL_WRITEMASK = 0x0B98;
184  const GLenum STENCIL_BACK_FUNC = 0x8800;
185  const GLenum STENCIL_BACK_FAIL = 0x8801;
186  const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
187  const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
188  const GLenum STENCIL_BACK_REF = 0x8CA3;
189  const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4;
190  const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5;
191  const GLenum VIEWPORT = 0x0BA2;
192  const GLenum SCISSOR_BOX = 0x0C10;
193  /* SCISSOR_TEST */
194  const GLenum COLOR_CLEAR_VALUE = 0x0C22;
195  const GLenum COLOR_WRITEMASK = 0x0C23;
196  const GLenum UNPACK_ALIGNMENT = 0x0CF5;
197  const GLenum PACK_ALIGNMENT = 0x0D05;
198  const GLenum MAX_TEXTURE_SIZE = 0x0D33;
199  const GLenum MAX_VIEWPORT_DIMS = 0x0D3A;
200  const GLenum SUBPIXEL_BITS = 0x0D50;
201  const GLenum RED_BITS = 0x0D52;
202  const GLenum GREEN_BITS = 0x0D53;
203  const GLenum BLUE_BITS = 0x0D54;
204  const GLenum ALPHA_BITS = 0x0D55;
205  const GLenum DEPTH_BITS = 0x0D56;
206  const GLenum STENCIL_BITS = 0x0D57;
207  const GLenum POLYGON_OFFSET_UNITS = 0x2A00;
208  /* POLYGON_OFFSET_FILL */
209  const GLenum POLYGON_OFFSET_FACTOR = 0x8038;
210  const GLenum TEXTURE_BINDING_2D = 0x8069;
211  const GLenum SAMPLE_BUFFERS = 0x80A8;
212  const GLenum SAMPLES = 0x80A9;
213  const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA;
214  const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB;
215 
216  /* GetTextureParameter */
217  /* TEXTURE_MAG_FILTER */
218  /* TEXTURE_MIN_FILTER */
219  /* TEXTURE_WRAP_S */
220  /* TEXTURE_WRAP_T */
221 
222  const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3;
223 
224  /* HintMode */
225  const GLenum DONT_CARE = 0x1100;
226  const GLenum FASTEST = 0x1101;
227  const GLenum NICEST = 0x1102;
228 
229  /* HintTarget */
230  const GLenum GENERATE_MIPMAP_HINT = 0x8192;
231 
232  /* DataType */
233  const GLenum BYTE = 0x1400;
234  const GLenum UNSIGNED_BYTE = 0x1401;
235  const GLenum SHORT = 0x1402;
236  const GLenum UNSIGNED_SHORT = 0x1403;
237  const GLenum INT = 0x1404;
238  const GLenum UNSIGNED_INT = 0x1405;
239  const GLenum FLOAT = 0x1406;
240 
241  /* PixelFormat */
242  const GLenum DEPTH_COMPONENT = 0x1902;
243  const GLenum ALPHA = 0x1906;
244  const GLenum RGB = 0x1907;
245  const GLenum RGBA = 0x1908;
246  const GLenum LUMINANCE = 0x1909;
247  const GLenum LUMINANCE_ALPHA = 0x190A;
248 
249  /* PixelType */
250  /* UNSIGNED_BYTE */
251  const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033;
252  const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034;
253  const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363;
254 
255  /* Shaders */
256  const GLenum FRAGMENT_SHADER = 0x8B30;
257  const GLenum VERTEX_SHADER = 0x8B31;
258  const GLenum MAX_VERTEX_ATTRIBS = 0x8869;
259  const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
260  const GLenum MAX_VARYING_VECTORS = 0x8DFC;
261  const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
262  const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
263  const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872;
264  const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
265  const GLenum SHADER_TYPE = 0x8B4F;
266  const GLenum DELETE_STATUS = 0x8B80;
267  const GLenum LINK_STATUS = 0x8B82;
268  const GLenum VALIDATE_STATUS = 0x8B83;
269  const GLenum ATTACHED_SHADERS = 0x8B85;
270  const GLenum ACTIVE_UNIFORMS = 0x8B86;
271  const GLenum ACTIVE_ATTRIBUTES = 0x8B89;
272  const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C;
273  const GLenum CURRENT_PROGRAM = 0x8B8D;
274 
275  /* StencilFunction */
276  const GLenum NEVER = 0x0200;
277  const GLenum LESS = 0x0201;
278  const GLenum EQUAL = 0x0202;
279  const GLenum LEQUAL = 0x0203;
280  const GLenum GREATER = 0x0204;
281  const GLenum NOTEQUAL = 0x0205;
282  const GLenum GEQUAL = 0x0206;
283  const GLenum ALWAYS = 0x0207;
284 
285  /* StencilOp */
286  /* ZERO */
287  const GLenum KEEP = 0x1E00;
288  const GLenum REPLACE = 0x1E01;
289  const GLenum INCR = 0x1E02;
290  const GLenum DECR = 0x1E03;
291  const GLenum INVERT = 0x150A;
292  const GLenum INCR_WRAP = 0x8507;
293  const GLenum DECR_WRAP = 0x8508;
294 
295  /* StringName */
296  const GLenum VENDOR = 0x1F00;
297  const GLenum RENDERER = 0x1F01;
298  const GLenum VERSION = 0x1F02;
299 
300  /* TextureMagFilter */
301  const GLenum NEAREST = 0x2600;
302  const GLenum LINEAR = 0x2601;
303 
304  /* TextureMinFilter */
305  /* NEAREST */
306  /* LINEAR */
307  const GLenum NEAREST_MIPMAP_NEAREST = 0x2700;
308  const GLenum LINEAR_MIPMAP_NEAREST = 0x2701;
309  const GLenum NEAREST_MIPMAP_LINEAR = 0x2702;
310  const GLenum LINEAR_MIPMAP_LINEAR = 0x2703;
311 
312  /* TextureParameterName */
313  const GLenum TEXTURE_MAG_FILTER = 0x2800;
314  const GLenum TEXTURE_MIN_FILTER = 0x2801;
315  const GLenum TEXTURE_WRAP_S = 0x2802;
316  const GLenum TEXTURE_WRAP_T = 0x2803;
317 
318  /* TextureTarget */
319  /* TEXTURE_2D */
320  const GLenum TEXTURE = 0x1702;
321 
322  const GLenum TEXTURE_CUBE_MAP = 0x8513;
323  const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514;
324  const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
325  const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
326  const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
327  const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
328  const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
329  const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
330  const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
331 
332  /* TextureUnit */
333  const GLenum TEXTURE0 = 0x84C0;
334  const GLenum TEXTURE1 = 0x84C1;
335  const GLenum TEXTURE2 = 0x84C2;
336  const GLenum TEXTURE3 = 0x84C3;
337  const GLenum TEXTURE4 = 0x84C4;
338  const GLenum TEXTURE5 = 0x84C5;
339  const GLenum TEXTURE6 = 0x84C6;
340  const GLenum TEXTURE7 = 0x84C7;
341  const GLenum TEXTURE8 = 0x84C8;
342  const GLenum TEXTURE9 = 0x84C9;
343  const GLenum TEXTURE10 = 0x84CA;
344  const GLenum TEXTURE11 = 0x84CB;
345  const GLenum TEXTURE12 = 0x84CC;
346  const GLenum TEXTURE13 = 0x84CD;
347  const GLenum TEXTURE14 = 0x84CE;
348  const GLenum TEXTURE15 = 0x84CF;
349  const GLenum TEXTURE16 = 0x84D0;
350  const GLenum TEXTURE17 = 0x84D1;
351  const GLenum TEXTURE18 = 0x84D2;
352  const GLenum TEXTURE19 = 0x84D3;
353  const GLenum TEXTURE20 = 0x84D4;
354  const GLenum TEXTURE21 = 0x84D5;
355  const GLenum TEXTURE22 = 0x84D6;
356  const GLenum TEXTURE23 = 0x84D7;
357  const GLenum TEXTURE24 = 0x84D8;
358  const GLenum TEXTURE25 = 0x84D9;
359  const GLenum TEXTURE26 = 0x84DA;
360  const GLenum TEXTURE27 = 0x84DB;
361  const GLenum TEXTURE28 = 0x84DC;
362  const GLenum TEXTURE29 = 0x84DD;
363  const GLenum TEXTURE30 = 0x84DE;
364  const GLenum TEXTURE31 = 0x84DF;
365  const GLenum ACTIVE_TEXTURE = 0x84E0;
366 
367  /* TextureWrapMode */
368  const GLenum REPEAT = 0x2901;
369  const GLenum CLAMP_TO_EDGE = 0x812F;
370  const GLenum MIRRORED_REPEAT = 0x8370;
371 
372  /* Uniform Types */
373  const GLenum FLOAT_VEC2 = 0x8B50;
374  const GLenum FLOAT_VEC3 = 0x8B51;
375  const GLenum FLOAT_VEC4 = 0x8B52;
376  const GLenum INT_VEC2 = 0x8B53;
377  const GLenum INT_VEC3 = 0x8B54;
378  const GLenum INT_VEC4 = 0x8B55;
379  const GLenum BOOL = 0x8B56;
380  const GLenum BOOL_VEC2 = 0x8B57;
381  const GLenum BOOL_VEC3 = 0x8B58;
382  const GLenum BOOL_VEC4 = 0x8B59;
383  const GLenum FLOAT_MAT2 = 0x8B5A;
384  const GLenum FLOAT_MAT3 = 0x8B5B;
385  const GLenum FLOAT_MAT4 = 0x8B5C;
386  const GLenum SAMPLER_2D = 0x8B5E;
387  const GLenum SAMPLER_CUBE = 0x8B60;
388 
389  /* Vertex Arrays */
390  const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
391  const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
392  const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
393  const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
394  const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
395  const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
396  const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
397 
398  /* Shader Source */
399  const GLenum COMPILE_STATUS = 0x8B81;
400 
401  /* Shader Precision-Specified Types */
402  const GLenum LOW_FLOAT = 0x8DF0;
403  const GLenum MEDIUM_FLOAT = 0x8DF1;
404  const GLenum HIGH_FLOAT = 0x8DF2;
405  const GLenum LOW_INT = 0x8DF3;
406  const GLenum MEDIUM_INT = 0x8DF4;
407  const GLenum HIGH_INT = 0x8DF5;
408 
409  /* Framebuffer Object. */
410  const GLenum FRAMEBUFFER = 0x8D40;
411  const GLenum RENDERBUFFER = 0x8D41;
412 
413  const GLenum RGBA4 = 0x8056;
414  const GLenum RGB5_A1 = 0x8057;
415  const GLenum RGB565 = 0x8D62;
416  const GLenum DEPTH_COMPONENT16 = 0x81A5;
417  const GLenum STENCIL_INDEX = 0x1901;
418  const GLenum STENCIL_INDEX8 = 0x8D48;
419  const GLenum DEPTH_STENCIL = 0x84F9;
420 
421  const GLenum RENDERBUFFER_WIDTH = 0x8D42;
422  const GLenum RENDERBUFFER_HEIGHT = 0x8D43;
423  const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
424  const GLenum RENDERBUFFER_RED_SIZE = 0x8D50;
425  const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51;
426  const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52;
427  const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53;
428  const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54;
429  const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55;
430 
431  const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
432  const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
433  const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
434  const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
435 
436  const GLenum COLOR_ATTACHMENT0 = 0x8CE0;
437  const GLenum DEPTH_ATTACHMENT = 0x8D00;
438  const GLenum STENCIL_ATTACHMENT = 0x8D20;
439  const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A;
440 
441  const GLenum NONE = 0;
442 
443  const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5;
444  const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
445  const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
446  const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
447  const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
448 
449  const GLenum FRAMEBUFFER_BINDING = 0x8CA6;
450  const GLenum RENDERBUFFER_BINDING = 0x8CA7;
451  const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8;
452 
453  const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506;
454 
455  /* WebGL-specific enums */
456  const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240;
457  const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
458  const GLenum CONTEXT_LOST_WEBGL = 0x9242;
459  const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
460  const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
461 
462  readonly attribute GLsizei drawingBufferWidth;
463  readonly attribute GLsizei drawingBufferHeight;
464 
465  [StrictTypeChecking, RaisesException] void activeTexture(GLenum texture);
466  [StrictTypeChecking, RaisesException] void attachShader(WebGLProgram program, WebGLShader shader);
467  [StrictTypeChecking, RaisesException] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name);
468  [StrictTypeChecking, RaisesException] void bindBuffer(GLenum target, WebGLBuffer buffer);
469  [StrictTypeChecking, RaisesException] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer);
470  [StrictTypeChecking, RaisesException] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer);
471  [StrictTypeChecking, RaisesException] void bindTexture(GLenum target, WebGLTexture texture);
472  [StrictTypeChecking] void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
473  [StrictTypeChecking] void blendEquation(GLenum mode);
474  [StrictTypeChecking] void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
475  [StrictTypeChecking] void blendFunc(GLenum sfactor, GLenum dfactor);
476  [StrictTypeChecking] void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
477  [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
478  [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage);
479  [StrictTypeChecking, RaisesException] void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
480  [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data);
481  [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView? data);
482 
483  [StrictTypeChecking] GLenum checkFramebufferStatus(GLenum target);
484  [StrictTypeChecking] void clear(GLbitfield mask);
485  [StrictTypeChecking] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
486  [StrictTypeChecking] void clearDepth(GLclampf depth);
487  [StrictTypeChecking] void clearStencil(GLint s);
488  [StrictTypeChecking] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
489  [StrictTypeChecking, RaisesException] void compileShader(WebGLShader shader);
490 
491  [StrictTypeChecking] void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
492  GLsizei width, GLsizei height, GLint border, ArrayBufferView data);
493  [StrictTypeChecking] void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
494  GLsizei width, GLsizei height, GLenum format, ArrayBufferView data);
495 
496  [StrictTypeChecking] void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
497  [StrictTypeChecking] void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
498 
499  [StrictTypeChecking] WebGLBuffer createBuffer();
500  [StrictTypeChecking] WebGLFramebuffer createFramebuffer();
501  [StrictTypeChecking] WebGLProgram createProgram();
502  [StrictTypeChecking] WebGLRenderbuffer createRenderbuffer();
503  [StrictTypeChecking, RaisesException] WebGLShader createShader(GLenum type);
504  [StrictTypeChecking] WebGLTexture createTexture();
505 
506  [StrictTypeChecking] void cullFace(GLenum mode);
507 
508  [StrictTypeChecking] void deleteBuffer(WebGLBuffer buffer);
509  [StrictTypeChecking] void deleteFramebuffer(WebGLFramebuffer framebuffer);
510  [StrictTypeChecking] void deleteProgram(WebGLProgram program);
511  [StrictTypeChecking] void deleteRenderbuffer(WebGLRenderbuffer renderbuffer);
512  [StrictTypeChecking] void deleteShader(WebGLShader shader);
513  [StrictTypeChecking] void deleteTexture(WebGLTexture texture);
514 
515  [StrictTypeChecking] void depthFunc(GLenum func);
516  [StrictTypeChecking] void depthMask(GLboolean flag);
517  [StrictTypeChecking] void depthRange(GLclampf zNear, GLclampf zFar);
518  [StrictTypeChecking, RaisesException] void detachShader(WebGLProgram program, WebGLShader shader);
519  [StrictTypeChecking] void disable(GLenum cap);
520  [StrictTypeChecking, RaisesException] void disableVertexAttribArray(GLuint index);
521  [StrictTypeChecking, RaisesException] void drawArrays(GLenum mode, GLint first, GLsizei count);
522  [StrictTypeChecking, RaisesException] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset);
523 
524  [StrictTypeChecking] void enable(GLenum cap);
525  [StrictTypeChecking, RaisesException] void enableVertexAttribArray(GLuint index);
526  [StrictTypeChecking] void finish();
527  [StrictTypeChecking] void flush();
528  [StrictTypeChecking, RaisesException] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer);
529  [StrictTypeChecking, RaisesException] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level);
530  [StrictTypeChecking] void frontFace(GLenum mode);
531  [StrictTypeChecking] void generateMipmap(GLenum target);
532 
533  [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index);
534  [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index);
535 
536  [StrictTypeChecking, Custom, RaisesException] void getAttachedShaders(WebGLProgram program);
537 
538  [StrictTypeChecking] GLint getAttribLocation(WebGLProgram program, DOMString name);
539 
540  [StrictTypeChecking, Custom] any getBufferParameter(GLenum target, GLenum pname);
541 
542  [StrictTypeChecking] WebGLContextAttributes getContextAttributes();
543 
544  [StrictTypeChecking] GLenum getError();
545 
546  // object getExtension(DOMString name);
547  [StrictTypeChecking, Custom] any getExtension(DOMString name);
548 
549  [StrictTypeChecking, Custom, RaisesException] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname);
550  [StrictTypeChecking, Custom, RaisesException] any getParameter(GLenum pname);
551  [StrictTypeChecking, Custom, RaisesException] any getProgramParameter(WebGLProgram program, GLenum pname);
552  [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getProgramInfoLog(WebGLProgram program);
553  [StrictTypeChecking, Custom, RaisesException] any getRenderbufferParameter(GLenum target, GLenum pname);
554  [StrictTypeChecking, Custom, RaisesException] any getShaderParameter(WebGLShader shader, GLenum pname);
555 
556  [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderInfoLog(WebGLShader shader);
557 
558  [StrictTypeChecking, RaisesException] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
559 
560  [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderSource(WebGLShader shader);
561 
562  [StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions();
563 
564  [StrictTypeChecking, Custom, RaisesException] any getTexParameter(GLenum target, GLenum pname);
565 
566  [StrictTypeChecking, Custom, RaisesException] any getUniform(WebGLProgram program, WebGLUniformLocation location);
567 
568  [StrictTypeChecking, RaisesException] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name);
569 
570  [StrictTypeChecking, Custom, RaisesException] any getVertexAttrib(GLuint index, GLenum pname);
571 
572  [StrictTypeChecking] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
573 
574  [StrictTypeChecking] void hint(GLenum target, GLenum mode);
575  [StrictTypeChecking] GLboolean isBuffer(WebGLBuffer buffer);
576  [StrictTypeChecking] GLboolean isContextLost();
577  [StrictTypeChecking] GLboolean isEnabled(GLenum cap);
578  [StrictTypeChecking] GLboolean isFramebuffer(WebGLFramebuffer framebuffer);
579  [StrictTypeChecking] GLboolean isProgram(WebGLProgram program);
580  [StrictTypeChecking] GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer);
581  [StrictTypeChecking] GLboolean isShader(WebGLShader shader);
582  [StrictTypeChecking] GLboolean isTexture(WebGLTexture texture);
583  [StrictTypeChecking] void lineWidth(GLfloat width);
584  [StrictTypeChecking, RaisesException] void linkProgram(WebGLProgram program);
585  [StrictTypeChecking] void pixelStorei(GLenum pname, GLint param);
586  [StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units);
587 
588  [StrictTypeChecking, RaisesException] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels);
589 
590  [StrictTypeChecking] void releaseShaderCompiler();
591  [StrictTypeChecking] void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
592  [StrictTypeChecking] void sampleCoverage(GLclampf value, GLboolean invert);
593  [StrictTypeChecking] void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
594  [StrictTypeChecking, RaisesException] void shaderSource(WebGLShader shader, DOMString string);
595  [StrictTypeChecking] void stencilFunc(GLenum func, GLint ref, GLuint mask);
596  [StrictTypeChecking] void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
597  [StrictTypeChecking] void stencilMask(GLuint mask);
598  [StrictTypeChecking] void stencilMaskSeparate(GLenum face, GLuint mask);
599  [StrictTypeChecking] void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
600  [StrictTypeChecking] void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
601 
602  [StrictTypeChecking] void texParameterf(GLenum target, GLenum pname, GLfloat param);
603  [StrictTypeChecking] void texParameteri(GLenum target, GLenum pname, GLint param);
604 
605  // Supported forms:
606  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
607  GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
608  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
609  GLenum format, GLenum type, ImageData? pixels);
610  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
611  GLenum format, GLenum type, HTMLImageElement? image);
612  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
613  GLenum format, GLenum type, HTMLCanvasElement? canvas);
614 #if defined(ENABLE_VIDEO) && ENABLE_VIDEO
615  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
616  GLenum format, GLenum type, HTMLVideoElement? video);
617 #endif
618 
619  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
620  GLsizei width, GLsizei height,
621  GLenum format, GLenum type, ArrayBufferView? pixels);
622  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
623  GLenum format, GLenum type, ImageData? pixels);
624  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
625  GLenum format, GLenum type, HTMLImageElement? image);
626  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
627  GLenum format, GLenum type, HTMLCanvasElement? canvas);
628 #if defined(ENABLE_VIDEO) && ENABLE_VIDEO
629  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
630  GLenum format, GLenum type, HTMLVideoElement? video);
631 #endif
632 
633  [StrictTypeChecking, RaisesException] void uniform1f(WebGLUniformLocation location, GLfloat x);
634  [StrictTypeChecking, Custom, RaisesException] void uniform1fv(WebGLUniformLocation location, Float32Array v);
635  [StrictTypeChecking, RaisesException] void uniform1i(WebGLUniformLocation location, GLint x);
636  [StrictTypeChecking, Custom, RaisesException] void uniform1iv(WebGLUniformLocation location, Int32Array v);
637  [StrictTypeChecking, RaisesException] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y);
638  [StrictTypeChecking, Custom, RaisesException] void uniform2fv(WebGLUniformLocation location, Float32Array v);
639  [StrictTypeChecking, RaisesException] void uniform2i(WebGLUniformLocation location, GLint x, GLint y);
640  [StrictTypeChecking, Custom, RaisesException] void uniform2iv(WebGLUniformLocation location, Int32Array v);
641  [StrictTypeChecking, RaisesException] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z);
642  [StrictTypeChecking, Custom, RaisesException] void uniform3fv(WebGLUniformLocation location, Float32Array v);
643  [StrictTypeChecking, RaisesException] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z);
644  [StrictTypeChecking, Custom, RaisesException] void uniform3iv(WebGLUniformLocation location, Int32Array v);
645  [StrictTypeChecking, RaisesException] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
646  [StrictTypeChecking, Custom, RaisesException] void uniform4fv(WebGLUniformLocation location, Float32Array v);
647  [StrictTypeChecking, RaisesException] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w);
648  [StrictTypeChecking, Custom, RaisesException] void uniform4iv(WebGLUniformLocation location, Int32Array v);
649 
650  [StrictTypeChecking, Custom, RaisesException] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
651  [StrictTypeChecking, Custom, RaisesException] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
652  [StrictTypeChecking, Custom, RaisesException] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
653 
654  [StrictTypeChecking, RaisesException] void useProgram(WebGLProgram program);
655  [StrictTypeChecking, RaisesException] void validateProgram(WebGLProgram program);
656 
657  [StrictTypeChecking] void vertexAttrib1f(GLuint indx, GLfloat x);
658  [StrictTypeChecking, Custom] void vertexAttrib1fv(GLuint indx, Float32Array values);
659  [StrictTypeChecking] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
660  [StrictTypeChecking, Custom] void vertexAttrib2fv(GLuint indx, Float32Array values);
661  [StrictTypeChecking] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
662  [StrictTypeChecking, Custom] void vertexAttrib3fv(GLuint indx, Float32Array values);
663  [StrictTypeChecking] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
664  [StrictTypeChecking, Custom] void vertexAttrib4fv(GLuint indx, Float32Array values);
665  [StrictTypeChecking, RaisesException] void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized,
666  GLsizei stride, GLintptr offset);
667 
668  [StrictTypeChecking] void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 30] interface WebGL1RenderingContext : WebGLRenderingContextBase {
66931};
working copy

Source/WebCore/html/canvas/WebGL2RenderingContext.cpp

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEBGL)
 29#include "WebGL2RenderingContext.h"
 30
 31namespace WebCore {
 32
 33WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
 34 : WebGLRenderingContextBase(passedCanvas, attributes)
 35{
 36 m_type = "webgl2";
 37}
 38
 39WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
 40 GraphicsContext3D::Attributes attributes) : WebGLRenderingContextBase(passedCanvas, context, attributes)
 41{
 42 m_type = "webgl2";
 43}
 44} // namespace WebCore
 45
 46#endif // ENABLE(WEBGL)
0

Source/WebCore/html/canvas/WebGL2RenderingContext.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WebGL2RenderingContext_h
 27#define WebGL2RenderingContext_h
 28
 29#include "WebGLRenderingContextBase.h"
 30
 31namespace WebCore {
 32
 33class WebGL2RenderingContext final : public WebGLRenderingContextBase {
 34public:
 35 WebGL2RenderingContext(HTMLCanvasElement*, GraphicsContext3D::Attributes);
 36 WebGL2RenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes);
 37};
 38
 39} // namespace WebCore
 40
 41#endif
0

Source/WebCore/html/canvas/WebGL2RenderingContext.idl

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26[
 27 Conditional=WEBGL,
 28 JSCustomMarkFunction,
 29 DoNotCheckConstants,
 30] interface WebGL2RenderingContext : WebGLRenderingContextBase {
 31};
0

Source/WebCore/html/canvas/WebGLBuffer.cpp

3030#include "WebGLBuffer.h"
3131
3232#include "WebGLContextGroup.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx)
 37PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContextBase* ctx)
3838{
3939 return adoptRef(new WebGLBuffer(ctx));
4040}
4141
42 WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx)
 42WebGLBuffer::WebGLBuffer(WebGLRenderingContextBase* ctx)
4343 : WebGLSharedObject(ctx)
4444 , m_target(0)
4545 , m_byteLength(0)
178372

Source/WebCore/html/canvas/WebGLBuffer.h

@@class WebGLBuffer final : public WebGLSh
4141public:
4242 virtual ~WebGLBuffer();
4343
44  static PassRefPtr<WebGLBuffer> create(WebGLRenderingContext*);
 44 static PassRefPtr<WebGLBuffer> create(WebGLRenderingContextBase*);
4545
4646 bool associateBufferData(GC3Dsizeiptr size);
4747 bool associateBufferData(JSC::ArrayBuffer*);

@@public:
6666 bool hasEverBeenBound() const { return object() && m_target; }
6767
6868protected:
69  WebGLBuffer(WebGLRenderingContext*);
 69 WebGLBuffer(WebGLRenderingContextBase*);
7070
7171 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
7272
178372

Source/WebCore/html/canvas/WebGLCompressedTextureATC.cpp

3333
3434namespace WebCore {
3535
36 WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContext* context)
 36WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContextBase* context)
3737 : WebGLExtension(context)
3838{
3939 context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGB_AMD);

@@WebGLExtension::ExtensionName WebGLCompr
5050 return WebGLCompressedTextureATCName;
5151}
5252
53 bool WebGLCompressedTextureATC::supported(WebGLRenderingContext* context)
 53bool WebGLCompressedTextureATC::supported(WebGLRenderingContextBase* context)
5454{
5555 Extensions3D* extensions = context->graphicsContext3D()->getExtensions();
5656 return extensions->supports("GL_AMD_compressed_ATC_texture");
178372

Source/WebCore/html/canvas/WebGLCompressedTextureATC.h

@@class WebGLTexture;
3434
3535class WebGLCompressedTextureATC final : public WebGLExtension {
3636public:
37  explicit WebGLCompressedTextureATC(WebGLRenderingContext*);
 37 explicit WebGLCompressedTextureATC(WebGLRenderingContextBase*);
3838 virtual ~WebGLCompressedTextureATC();
3939
40  static bool supported(WebGLRenderingContext*);
 40 static bool supported(WebGLRenderingContextBase*);
4141
4242 virtual ExtensionName getName() const override;
4343};
178372

Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.cpp

3030#include "WebGLCompressedTexturePVRTC.h"
3131
3232#include "Extensions3D.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContext* context)
 37WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContextBase* context)
3838 : WebGLExtension(context)
3939{
4040 context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG);

@@WebGLExtension::ExtensionName WebGLCompr
5252 return WebGLCompressedTexturePVRTCName;
5353}
5454
55 bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContext* context)
 55bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContextBase* context)
5656{
5757 Extensions3D* extensions = context->graphicsContext3D()->getExtensions();
5858 return extensions->supports("GL_IMG_texture_compression_pvrtc");
178372

Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.h

@@namespace WebCore {
3232
3333class WebGLCompressedTexturePVRTC final : public WebGLExtension {
3434public:
35  explicit WebGLCompressedTexturePVRTC(WebGLRenderingContext*);
 35 explicit WebGLCompressedTexturePVRTC(WebGLRenderingContextBase*);
3636 virtual ~WebGLCompressedTexturePVRTC();
3737
38  static bool supported(WebGLRenderingContext*);
 38 static bool supported(WebGLRenderingContextBase*);
3939 virtual ExtensionName getName() const override;
4040};
4141
178372

Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.cpp

3030#include "WebGLCompressedTextureS3TC.h"
3131
3232#include "Extensions3D.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContext* context)
 37WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContextBase* context)
3838 : WebGLExtension(context)
3939{
4040 context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT);

@@WebGLExtension::ExtensionName WebGLCompr
5252 return WebGLCompressedTextureS3TCName;
5353}
5454
55 bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContext* context)
 55bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContextBase* context)
5656{
5757 Extensions3D* extensions = context->graphicsContext3D()->getExtensions();
5858 return extensions->supports("GL_EXT_texture_compression_s3tc")
178372

Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.h

@@class WebGLTexture;
3434
3535class WebGLCompressedTextureS3TC final : public WebGLExtension {
3636public:
37  explicit WebGLCompressedTextureS3TC(WebGLRenderingContext*);
 37 explicit WebGLCompressedTextureS3TC(WebGLRenderingContextBase*);
3838 virtual ~WebGLCompressedTextureS3TC();
3939
40  static bool supported(WebGLRenderingContext*);
 40 static bool supported(WebGLRenderingContextBase*);
4141
4242 virtual ExtensionName getName() const override;
4343};
178372

Source/WebCore/html/canvas/WebGLContextGroup.cpp

3030#include "WebGLContextGroup.h"
3131
3232#include "GraphicsContext3D.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434#include "WebGLSharedObject.h"
3535
3636namespace WebCore {

@@WebGLContextGroup::~WebGLContextGroup()
5353GraphicsContext3D* WebGLContextGroup::getAGraphicsContext3D()
5454{
5555 ASSERT(!m_contexts.isEmpty());
56  HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin();
 56 HashSet<WebGLRenderingContextBase*>::iterator it = m_contexts.begin();
5757 return (*it)->graphicsContext3D();
5858}
5959
60 void WebGLContextGroup::addContext(WebGLRenderingContext* context)
 60void WebGLContextGroup::addContext(WebGLRenderingContextBase* context)
6161{
6262 m_contexts.add(context);
6363}
6464
65 void WebGLContextGroup::removeContext(WebGLRenderingContext* context)
 65void WebGLContextGroup::removeContext(WebGLRenderingContextBase* context)
6666{
6767 // We must call detachAndRemoveAllObjects before removing the last context.
6868 if (m_contexts.size() == 1 && m_contexts.contains(context))

@@void WebGLContextGroup::detachAndRemoveA
8989 }
9090}
9191
92 void WebGLContextGroup::loseContextGroup(WebGLRenderingContext::LostContextMode mode)
 92void WebGLContextGroup::loseContextGroup(WebGLRenderingContextBase::LostContextMode mode)
9393{
94  for (HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
 94 for (HashSet<WebGLRenderingContextBase*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9595 (*it)->loseContextImpl(mode);
9696
9797 detachAndRemoveAllObjects();
178372

Source/WebCore/html/canvas/WebGLContextGroup.h

2626#ifndef WebGLContextGroup_h
2727#define WebGLContextGroup_h
2828
29 #include <WebGLRenderingContext.h>
 29#include <WebGLRenderingContextBase.h>
3030#include <wtf/HashSet.h>
3131#include <wtf/PassRefPtr.h>
3232#include <wtf/RefCounted.h>

@@namespace WebCore {
3636class GraphicsContext3D;
3737class WebGLExtension;
3838class WebGLSharedObject;
39 class WebGLRenderingContext;
 39class WebGLRenderingContextBase;
4040
4141typedef int ExceptionCode;
4242

@@public:
4545 static PassRefPtr<WebGLContextGroup> create();
4646 ~WebGLContextGroup();
4747
48  void addContext(WebGLRenderingContext*);
49  void removeContext(WebGLRenderingContext*);
 48 void addContext(WebGLRenderingContextBase*);
 49 void removeContext(WebGLRenderingContextBase*);
5050
5151 void addObject(WebGLSharedObject*);
5252 void removeObject(WebGLSharedObject*);
5353
5454 GraphicsContext3D* getAGraphicsContext3D();
5555
56  void loseContextGroup(WebGLRenderingContext::LostContextMode);
 56 void loseContextGroup(WebGLRenderingContextBase::LostContextMode);
5757
5858 private:
5959 friend class WebGLObject;

@@public:
6262
6363 void detachAndRemoveAllObjects();
6464
65  HashSet<WebGLRenderingContext*> m_contexts;
 65 HashSet<WebGLRenderingContextBase*> m_contexts;
6666 HashSet<WebGLSharedObject*> m_groupObjects;
6767};
6868
178372

Source/WebCore/html/canvas/WebGLContextObject.cpp

2929
3030#include "WebGLContextObject.h"
3131
32 #include "WebGLRenderingContext.h"
 32#include "WebGLRenderingContextBase.h"
3333
3434namespace WebCore {
3535
36 WebGLContextObject::WebGLContextObject(WebGLRenderingContext* context)
 36WebGLContextObject::WebGLContextObject(WebGLRenderingContextBase* context)
3737 : WebGLObject(context)
3838 , m_context(context)
3939{
178372

Source/WebCore/html/canvas/WebGLContextObject.h

3131namespace WebCore {
3232
3333class GraphicsContext3D;
34 class WebGLRenderingContext;
 34class WebGLRenderingContextBase;
3535
3636// WebGLContextObject the base class for objects that are owned by a specific
3737// WebGLRenderingContext.

@@class WebGLContextObject : public WebGLO
3939public:
4040 virtual ~WebGLContextObject();
4141
42  WebGLRenderingContext* context() const { return m_context; }
 42 WebGLRenderingContextBase* context() const { return m_context; }
4343
44  virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContext* context) const override
 44 virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase* context) const override
4545 {
4646 return context == m_context;
4747 }

@@public:
4949 void detachContext();
5050
5151protected:
52  WebGLContextObject(WebGLRenderingContext*);
 52 WebGLContextObject(WebGLRenderingContextBase*);
5353
5454 virtual bool hasGroupOrContext() const override
5555 {

@@protected:
5959 virtual GraphicsContext3D* getAGraphicsContext3D() const override;
6060
6161private:
62  WebGLRenderingContext* m_context;
 62 WebGLRenderingContextBase* m_context;
6363};
6464
6565} // namespace WebCore
178372

Source/WebCore/html/canvas/WebGLDebugRendererInfo.cpp

2929
3030#include "WebGLDebugRendererInfo.h"
3131
32 #include "WebGLRenderingContext.h"
 32#include "WebGLRenderingContextBase.h"
3333
3434namespace WebCore {
3535
36 WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContext* context)
 36WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContextBase* context)
3737 : WebGLExtension(context)
3838{
3939}
178372

Source/WebCore/html/canvas/WebGLDebugRendererInfo.h

@@public:
3737 UNMASKED_RENDERER_WEBGL = 0x9246
3838 };
3939
40  explicit WebGLDebugRendererInfo(WebGLRenderingContext*);
 40 explicit WebGLDebugRendererInfo(WebGLRenderingContextBase*);
4141 virtual ~WebGLDebugRendererInfo();
4242
4343 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/WebGLDebugShaders.cpp

3030#include "WebGLDebugShaders.h"
3131
3232#include "Extensions3D.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434#include "WebGLShader.h"
3535
3636namespace WebCore {
3737
38 WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContext* context)
 38WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContextBase* context)
3939 : WebGLExtension(context)
4040{
4141}
178372

Source/WebCore/html/canvas/WebGLDebugShaders.h

@@typedef int ExceptionCode;
3636
3737class WebGLDebugShaders final : public WebGLExtension {
3838public:
39  explicit WebGLDebugShaders(WebGLRenderingContext*);
 39 explicit WebGLDebugShaders(WebGLRenderingContextBase*);
4040 virtual ~WebGLDebugShaders();
4141
4242 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/WebGLDepthTexture.cpp

3333
3434namespace WebCore {
3535
36 WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContext* context)
 36WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContextBase* context)
3737 : WebGLExtension(context)
3838{
3939}
178372

Source/WebCore/html/canvas/WebGLDepthTexture.h

@@namespace WebCore {
3232
3333class WebGLDepthTexture final : public WebGLExtension {
3434public:
35  explicit WebGLDepthTexture(WebGLRenderingContext*);
 35 explicit WebGLDepthTexture(WebGLRenderingContextBase*);
3636 virtual ~WebGLDepthTexture();
3737
3838 static bool supported(GraphicsContext3D*);
178372

Source/WebCore/html/canvas/WebGLDrawBuffers.cpp

3232
3333namespace WebCore {
3434
35 WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContext* context)
 35WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContextBase* context)
3636 : WebGLExtension(context)
3737{
3838}

@@WebGLExtension::ExtensionName WebGLDrawB
4848
4949#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000)
5050
51 bool WebGLDrawBuffers::supported(WebGLRenderingContext*)
 51bool WebGLDrawBuffers::supported(WebGLRenderingContextBase*)
5252{
5353 return false;
5454}
5555
5656#else
5757
58 bool WebGLDrawBuffers::supported(WebGLRenderingContext* context)
 58bool WebGLDrawBuffers::supported(WebGLRenderingContextBase* context)
5959{
6060 Extensions3D* extensions = context->graphicsContext3D()->getExtensions();
6161 return extensions->supports("GL_EXT_draw_buffers")

@@void WebGLDrawBuffers::drawBuffersWEBGL(
9999}
100100
101101// static
102 bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglContext)
 102bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase* webglContext)
103103{
104104 GraphicsContext3D* context = webglContext->graphicsContext3D();
105105
178372

Source/WebCore/html/canvas/WebGLDrawBuffers.h

@@namespace WebCore {
3232
3333class WebGLDrawBuffers final : public WebGLExtension {
3434public:
35  explicit WebGLDrawBuffers(WebGLRenderingContext*);
 35 explicit WebGLDrawBuffers(WebGLRenderingContextBase*);
3636 virtual ~WebGLDrawBuffers();
3737
38  static bool supported(WebGLRenderingContext*);
 38 static bool supported(WebGLRenderingContextBase*);
3939
4040 virtual ExtensionName getName() const override;
4141
4242 void drawBuffersWEBGL(const Vector<GC3Denum>& buffers);
4343
4444private:
45  static bool satisfiesWebGLRequirements(WebGLRenderingContext*);
 45 static bool satisfiesWebGLRequirements(WebGLRenderingContextBase*);
4646};
4747
4848} // namespace WebCore
178372

Source/WebCore/html/canvas/WebGLExtension.cpp

3131
3232namespace WebCore {
3333
34 WebGLExtension::WebGLExtension(WebGLRenderingContext* context)
 34WebGLExtension::WebGLExtension(WebGLRenderingContextBase* context)
3535 : m_context(context)
3636{
3737}
178372

Source/WebCore/html/canvas/WebGLExtension.h

2626#ifndef WebGLExtension_h
2727#define WebGLExtension_h
2828
29 #include "WebGLRenderingContext.h"
 29#include "WebGLRenderingContextBase.h"
3030
3131namespace WebCore {
3232

@@public:
6060
6161 void ref() { m_context->ref(); }
6262 void deref() { m_context->deref(); }
63  WebGLRenderingContext* context() { return m_context; }
 63 WebGLRenderingContextBase* context() { return m_context; }
6464
6565 virtual ~WebGLExtension();
6666 virtual ExtensionName getName() const = 0;
6767
6868protected:
69  WebGLExtension(WebGLRenderingContext*);
70  WebGLRenderingContext* m_context;
 69 WebGLExtension(WebGLRenderingContextBase*);
 70 WebGLRenderingContextBase* m_context;
7171};
7272
7373} // namespace WebCore
178372

Source/WebCore/html/canvas/WebGLFramebuffer.cpp

3232#include "Extensions3D.h"
3333#include "WebGLContextGroup.h"
3434#include "WebGLDrawBuffers.h"
35 #include "WebGLRenderingContext.h"
 35#include "WebGLRenderingContextBase.h"
3636
3737namespace WebCore {
3838

@@WebGLFramebuffer::WebGLAttachment::~WebG
269269{
270270}
271271
272 PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx)
 272PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContextBase* ctx)
273273{
274274 return adoptRef(new WebGLFramebuffer(ctx));
275275}
276276
277 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx)
 277WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx)
278278 : WebGLContextObject(ctx)
279279 , m_hasEverBeenBound(false)
280280{
178372

Source/WebCore/html/canvas/WebGLFramebuffer.h

@@public:
6161
6262 virtual ~WebGLFramebuffer();
6363
64  static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*);
 64 static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContextBase*);
6565
6666 void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level);
6767 void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*);

@@public:
101101 GC3Denum getDrawBuffer(GC3Denum);
102102
103103protected:
104  WebGLFramebuffer(WebGLRenderingContext*);
 104 WebGLFramebuffer(WebGLRenderingContextBase*);
105105
106106 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
107107
178372

Source/WebCore/html/canvas/WebGLLoseContext.cpp

2929
3030#include "WebGLLoseContext.h"
3131
32 #include "WebGLRenderingContext.h"
 32#include "WebGLRenderingContextBase.h"
3333
3434namespace WebCore {
3535
36 WebGLLoseContext::WebGLLoseContext(WebGLRenderingContext* context)
 36WebGLLoseContext::WebGLLoseContext(WebGLRenderingContextBase* context)
3737 : WebGLExtension(context)
3838{
3939}

@@WebGLExtension::ExtensionName WebGLLoseC
4949
5050void WebGLLoseContext::loseContext()
5151{
52  m_context->forceLostContext(WebGLRenderingContext::SyntheticLostContext);
 52 m_context->forceLostContext(WebGLRenderingContextBase::SyntheticLostContext);
5353}
5454
5555void WebGLLoseContext::restoreContext()
178372

Source/WebCore/html/canvas/WebGLLoseContext.h

3030
3131namespace WebCore {
3232
33 class WebGLRenderingContext;
 33class WebGLRenderingContextBase;
3434
3535class WebGLLoseContext final : public WebGLExtension {
3636public:
37  explicit WebGLLoseContext(WebGLRenderingContext*);
 37 explicit WebGLLoseContext(WebGLRenderingContextBase*);
3838 virtual ~WebGLLoseContext();
3939
4040 virtual ExtensionName getName() const override;
178372

Source/WebCore/html/canvas/WebGLObject.cpp

3434#include "WebGLDebugRendererInfo.h"
3535#include "WebGLDebugShaders.h"
3636#include "WebGLLoseContext.h"
37 #include "WebGLRenderingContext.h"
 37#include "WebGLRenderingContextBase.h"
3838
3939namespace WebCore {
4040
41 WebGLObject::WebGLObject(WebGLRenderingContext*)
 41WebGLObject::WebGLObject(WebGLRenderingContextBase*)
4242 : m_object(0)
4343 , m_attachmentCount(0)
4444 , m_deleted(false)
178372

Source/WebCore/html/canvas/WebGLObject.h

@@namespace WebCore {
3434
3535class GraphicsContext3D;
3636class WebGLContextGroup;
37 class WebGLRenderingContext;
 37class WebGLRenderingContextBase;
3838
3939class WebGLObject : public RefCounted<WebGLObject> {
4040public:

@@public:
5656 bool isDeleted() { return m_deleted; }
5757
5858 // True if this object belongs to the group or context.
59  virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContext*) const = 0;
 59 virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase*) const = 0;
6060
6161protected:
62  WebGLObject(WebGLRenderingContext*);
 62 WebGLObject(WebGLRenderingContextBase*);
6363
6464 // setObject should be only called once right after creating a WebGLObject.
6565 void setObject(Platform3DObject);
178372

Source/WebCore/html/canvas/WebGLProgram.cpp

3030#include "WebGLProgram.h"
3131
3232#include "WebGLContextGroup.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx)
 37PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase* ctx)
3838{
3939 return adoptRef(new WebGLProgram(ctx));
4040}
4141
42 WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
 42WebGLProgram::WebGLProgram(WebGLRenderingContextBase* ctx)
4343 : WebGLSharedObject(ctx)
4444 , m_linkStatus(false)
4545 , m_linkCount(0)
178372

Source/WebCore/html/canvas/WebGLProgram.h

@@class WebGLProgram final : public WebGLS
3939public:
4040 virtual ~WebGLProgram();
4141
42  static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*);
 42 static PassRefPtr<WebGLProgram> create(WebGLRenderingContextBase*);
4343
4444 unsigned numActiveAttribLocations();
4545 GC3Dint getActiveAttribLocation(GC3Duint index);

@@public:
6262 bool detachShader(WebGLShader*);
6363
6464protected:
65  WebGLProgram(WebGLRenderingContext*);
 65 WebGLProgram(WebGLRenderingContextBase*);
6666
6767 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
6868
178372

Source/WebCore/html/canvas/WebGLRenderbuffer.cpp

3030#include "WebGLRenderbuffer.h"
3131
3232#include "WebGLContextGroup.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* ctx)
 37PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContextBase* ctx)
3838{
3939 return adoptRef(new WebGLRenderbuffer(ctx));
4040}

@@WebGLRenderbuffer::~WebGLRenderbuffer()
4444 deleteObject(0);
4545}
4646
47 WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx)
 47WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContextBase* ctx)
4848 : WebGLSharedObject(ctx)
4949 , m_internalFormat(GraphicsContext3D::RGBA4)
5050 , m_initialized(false)
178372

Source/WebCore/html/canvas/WebGLRenderbuffer.h

@@class WebGLRenderbuffer final : public W
3737public:
3838 virtual ~WebGLRenderbuffer();
3939
40  static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*);
 40 static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContextBase*);
4141
4242 void setInternalFormat(GC3Denum internalformat)
4343 {

@@public:
6565 void setHasEverBeenBound() { m_hasEverBeenBound = true; }
6666
6767protected:
68  WebGLRenderbuffer(WebGLRenderingContext*);
 68 WebGLRenderbuffer(WebGLRenderingContextBase*);
6969
7070 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
7171
178372

Source/WebCore/html/canvas/WebGLRenderingContext.cpp

1 /*
2  * Copyright (C) 2009, 2013, 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if ENABLE(WEBGL)
29 
30 #include "WebGLRenderingContext.h"
31 
32 #include "ANGLEInstancedArrays.h"
33 #include "CachedImage.h"
34 #include "DOMWindow.h"
35 #include "Document.h"
36 #include "EXTBlendMinMax.h"
37 #include "EXTFragDepth.h"
38 #include "EXTShaderTextureLOD.h"
39 #include "EXTTextureFilterAnisotropic.h"
40 #include "EXTsRGB.h"
41 #include "ExceptionCode.h"
42 #include "Extensions3D.h"
43 #include "Frame.h"
44 #include "FrameLoader.h"
45 #include "FrameLoaderClient.h"
46 #include "FrameView.h"
47 #include "GraphicsContext.h"
48 #include "HTMLCanvasElement.h"
49 #include "HTMLImageElement.h"
50 #include "HTMLVideoElement.h"
51 #include "ImageBuffer.h"
52 #include "ImageData.h"
53 #include "IntSize.h"
54 #include "Logging.h"
55 #include "MainFrame.h"
56 #include "NotImplemented.h"
57 #include "OESElementIndexUint.h"
58 #include "OESStandardDerivatives.h"
59 #include "OESTextureFloat.h"
60 #include "OESTextureFloatLinear.h"
61 #include "OESTextureHalfFloat.h"
62 #include "OESTextureHalfFloatLinear.h"
63 #include "OESVertexArrayObject.h"
64 #include "Page.h"
65 #include "RenderBox.h"
66 #include "Settings.h"
67 #include "WebGLActiveInfo.h"
68 #include "WebGLBuffer.h"
69 #include "WebGLCompressedTextureATC.h"
70 #include "WebGLCompressedTexturePVRTC.h"
71 #include "WebGLCompressedTextureS3TC.h"
72 #include "WebGLContextAttributes.h"
73 #include "WebGLContextEvent.h"
74 #include "WebGLContextGroup.h"
75 #include "WebGLDebugRendererInfo.h"
76 #include "WebGLDebugShaders.h"
77 #include "WebGLDepthTexture.h"
78 #include "WebGLDrawBuffers.h"
79 #include "WebGLFramebuffer.h"
80 #include "WebGLLoseContext.h"
81 #include "WebGLProgram.h"
82 #include "WebGLRenderbuffer.h"
83 #include "WebGLShader.h"
84 #include "WebGLShaderPrecisionFormat.h"
85 #include "WebGLTexture.h"
86 #include "WebGLUniformLocation.h"
87 
88 #include <runtime/JSCInlines.h>
89 #include <runtime/TypedArrayInlines.h>
90 #include <runtime/Uint32Array.h>
91 #include <wtf/StdLibExtras.h>
92 #include <wtf/text/CString.h>
93 #include <wtf/text/StringBuilder.h>
94 
95 namespace WebCore {
96 
97 const double secondsBetweenRestoreAttempts = 1.0;
98 const int maxGLErrorsAllowedToConsole = 256;
99 
100 namespace {
101 
102  class ScopedDrawingBufferBinder {
103  public:
104  ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
105  : m_drawingBuffer(drawingBuffer)
106  , m_framebufferBinding(framebufferBinding)
107  {
108  // Commit DrawingBuffer if needed (e.g., for multisampling)
109  if (!m_framebufferBinding && m_drawingBuffer)
110  m_drawingBuffer->commit();
111  }
112 
113  ~ScopedDrawingBufferBinder()
114  {
115  // Restore DrawingBuffer if needed
116  if (!m_framebufferBinding && m_drawingBuffer)
117  m_drawingBuffer->bind();
118  }
119 
120  private:
121  DrawingBuffer* m_drawingBuffer;
122  WebGLFramebuffer* m_framebufferBinding;
123  };
124 
125  Platform3DObject objectOrZero(WebGLObject* object)
126  {
127  return object ? object->object() : 0;
128  }
129 
130  void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
131  {
132  ASSERT(clippedStart && clippedRange);
133  if (start < 0) {
134  range += start;
135  start = 0;
136  }
137  GC3Dint end = start + range;
138  if (end > sourceRange)
139  range -= end - sourceRange;
140  *clippedStart = start;
141  *clippedRange = range;
142  }
143 
144  // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
145  bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
146  GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
147  GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
148  {
149  ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
150  clip1D(x, width, sourceWidth, clippedX, clippedWidth);
151  clip1D(y, height, sourceHeight, clippedY, clippedHeight);
152  return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
153  }
154 
155  GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
156  {
157  if (value < min)
158  value = min;
159  if (value > max)
160  value = max;
161  return value;
162  }
163 
164  // Return true if a character belongs to the ASCII subset as defined in
165  // GLSL ES 1.0 spec section 3.1.
166  bool validateCharacter(unsigned char c)
167  {
168  // Printing characters are valid except " $ ` @ \ ' DEL.
169  if (c >= 32 && c <= 126
170  && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
171  return true;
172  // Horizontal tab, line feed, vertical tab, form feed, carriage return
173  // are also valid.
174  if (c >= 9 && c <= 13)
175  return true;
176  return false;
177  }
178 
179  bool isPrefixReserved(const String& name)
180  {
181  if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_"))
182  return true;
183  return false;
184  }
185 
186  // Strips comments from shader text. This allows non-ASCII characters
187  // to be used in comments without potentially breaking OpenGL
188  // implementations not expecting characters outside the GLSL ES set.
189  class StripComments {
190  public:
191  StripComments(const String& str)
192  : m_parseState(BeginningOfLine)
193  , m_sourceString(str)
194  , m_length(str.length())
195  , m_position(0)
196  {
197  parse();
198  }
199 
200  String result()
201  {
202  return m_builder.toString();
203  }
204 
205  private:
206  bool hasMoreCharacters() const
207  {
208  return (m_position < m_length);
209  }
210 
211  void parse()
212  {
213  while (hasMoreCharacters()) {
214  process(current());
215  // process() might advance the position.
216  if (hasMoreCharacters())
217  advance();
218  }
219  }
220 
221  void process(UChar);
222 
223  bool peek(UChar& character) const
224  {
225  if (m_position + 1 >= m_length)
226  return false;
227  character = m_sourceString[m_position + 1];
228  return true;
229  }
230 
231  UChar current() const
232  {
233  ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length);
234  return m_sourceString[m_position];
235  }
236 
237  void advance()
238  {
239  ++m_position;
240  }
241 
242  bool isNewline(UChar character) const
243  {
244  // Don't attempt to canonicalize newline related characters.
245  return (character == '\n' || character == '\r');
246  }
247 
248  void emit(UChar character)
249  {
250  m_builder.append(character);
251  }
252 
253  enum ParseState {
254  // Have not seen an ASCII non-whitespace character yet on
255  // this line. Possible that we might see a preprocessor
256  // directive.
257  BeginningOfLine,
258 
259  // Have seen at least one ASCII non-whitespace character
260  // on this line.
261  MiddleOfLine,
262 
263  // Handling a preprocessor directive. Passes through all
264  // characters up to the end of the line. Disables comment
265  // processing.
266  InPreprocessorDirective,
267 
268  // Handling a single-line comment. The comment text is
269  // replaced with a single space.
270  InSingleLineComment,
271 
272  // Handling a multi-line comment. Newlines are passed
273  // through to preserve line numbers.
274  InMultiLineComment
275  };
276 
277  ParseState m_parseState;
278  String m_sourceString;
279  unsigned m_length;
280  unsigned m_position;
281  StringBuilder m_builder;
282  };
283 
284  void StripComments::process(UChar c)
285  {
286  if (isNewline(c)) {
287  // No matter what state we are in, pass through newlines
288  // so we preserve line numbers.
289  emit(c);
290 
291  if (m_parseState != InMultiLineComment)
292  m_parseState = BeginningOfLine;
293 
294  return;
295  }
296 
297  UChar temp = 0;
298  switch (m_parseState) {
299  case BeginningOfLine:
300  if (WTF::isASCIISpace(c)) {
301  emit(c);
302  break;
303  }
304 
305  if (c == '#') {
306  m_parseState = InPreprocessorDirective;
307  emit(c);
308  break;
309  }
310 
311  // Transition to normal state and re-handle character.
312  m_parseState = MiddleOfLine;
313  process(c);
314  break;
315 
316  case MiddleOfLine:
317  if (c == '/' && peek(temp)) {
318  if (temp == '/') {
319  m_parseState = InSingleLineComment;
320  emit(' ');
321  advance();
322  break;
323  }
324 
325  if (temp == '*') {
326  m_parseState = InMultiLineComment;
327  // Emit the comment start in case the user has
328  // an unclosed comment and we want to later
329  // signal an error.
330  emit('/');
331  emit('*');
332  advance();
333  break;
334  }
335  }
336 
337  emit(c);
338  break;
339 
340  case InPreprocessorDirective:
341  // No matter what the character is, just pass it
342  // through. Do not parse comments in this state. This
343  // might not be the right thing to do long term, but it
344  // should handle the #error preprocessor directive.
345  emit(c);
346  break;
347 
348  case InSingleLineComment:
349  // The newline code at the top of this function takes care
350  // of resetting our state when we get out of the
351  // single-line comment. Swallow all other characters.
352  break;
353 
354  case InMultiLineComment:
355  if (c == '*' && peek(temp) && temp == '/') {
356  emit('*');
357  emit('/');
358  m_parseState = MiddleOfLine;
359  advance();
360  break;
361  }
362 
363  // Swallow all other characters. Unclear whether we may
364  // want or need to just emit a space per character to try
365  // to preserve column numbers for debugging purposes.
366  break;
367  }
368  }
369 } // namespace anonymous
370 
371 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
372  WTF_MAKE_FAST_ALLOCATED;
373 public:
374  explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { }
375  virtual void onContextLost() override { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); }
376  virtual ~WebGLRenderingContextLostCallback() {}
377 private:
378  WebGLRenderingContext* m_context;
379 };
380 
381 class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback {
382  WTF_MAKE_FAST_ALLOCATED;
383 public:
384  explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb) : m_context(cb) { }
385  virtual void onErrorMessage(const String& message, GC3Dint) override
386  {
387  if (m_context->m_synthesizedErrorsToConsole)
388  m_context->printGLErrorToConsole(message);
389  }
390  virtual ~WebGLRenderingContextErrorMessageCallback() { }
391 private:
392  WebGLRenderingContext* m_context;
393 };
394 
395 std::unique_ptr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
396 {
397  Document& document = canvas->document();
398  Frame* frame = document.frame();
399  if (!frame)
400  return nullptr;
401 
402  // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in
403  // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension.
404  if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) {
405  canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context."));
406  return nullptr;
407  }
408 
409  bool isPendingPolicyResolution = false;
410  Document& topDocument = document.topDocument();
411  Page* page = topDocument.page();
412  if (page && !topDocument.url().isLocalFile()) {
413  WebGLLoadPolicy policy = page->mainFrame().loader().client().webGLPolicyForURL(topDocument.url());
414 
415  if (policy == WebGLBlockCreation) {
416  LOG(WebGL, "The policy for this URL (%s) is to block WebGL.", topDocument.url().host().utf8().data());
417  return nullptr;
418  }
419 
420  if (policy == WebGLPendingCreation) {
421  LOG(WebGL, "WebGL policy is pending. May need to be resolved later.");
422  isPendingPolicyResolution = true;
423  }
424  }
425 
426  GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
427 
428  if (attributes.antialias) {
429  if (!frame->settings().openGLMultisamplingEnabled())
430  attributes.antialias = false;
431  }
432 
433  attributes.noExtensions = true;
434  attributes.shareResources = false;
435  attributes.preferDiscreteGPU = true;
436 
437  if (frame->settings().forceSoftwareWebGLRendering())
438  attributes.forceSoftwareRenderer = true;
439 
440  if (page)
441  attributes.devicePixelRatio = page->deviceScaleFactor();
442 
443  if (isPendingPolicyResolution) {
444  LOG(WebGL, "Create a WebGL context that looks real, but will require a policy resolution if used.");
445  std::unique_ptr<WebGLRenderingContext> renderingContext(new WebGLRenderingContext(canvas, attributes));
446  renderingContext->suspendIfNeeded();
447  return renderingContext;
448  }
449 
450  HostWindow* hostWindow = document.view()->root()->hostWindow();
451  RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
452 
453  if (!context || !context->makeContextCurrent()) {
454  canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
455  return nullptr;
456  }
457 
458  Extensions3D* extensions = context->getExtensions();
459  if (extensions->supports("GL_EXT_debug_marker"))
460  extensions->pushGroupMarkerEXT("WebGLRenderingContext");
461 
462  std::unique_ptr<WebGLRenderingContext> renderingContext(new WebGLRenderingContext(canvas, context, attributes));
463  renderingContext->suspendIfNeeded();
464 
465  return renderingContext;
466 }
467 
468 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
469  : CanvasRenderingContext(passedCanvas)
470  , ActiveDOMObject(&passedCanvas->document())
471  , m_context(0)
472  , m_drawingBuffer(0)
473  , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContext::dispatchContextLostEvent)
474  , m_restoreAllowed(false)
475  , m_restoreTimer(*this, &WebGLRenderingContext::maybeRestoreContext)
476  , m_generatedImageCache(0)
477  , m_contextLost(false)
478  , m_contextLostMode(SyntheticLostContext)
479  , m_attributes(attributes)
480  , m_synthesizedErrorsToConsole(true)
481  , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
482  , m_isPendingPolicyResolution(true)
483  , m_hasRequestedPolicyResolution(false)
484 {
485 }
486 
487 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
488  GraphicsContext3D::Attributes attributes)
489  : CanvasRenderingContext(passedCanvas)
490  , ActiveDOMObject(&passedCanvas->document())
491  , m_context(context)
492  , m_drawingBuffer(0)
493  , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContext::dispatchContextLostEvent)
494  , m_restoreAllowed(false)
495  , m_restoreTimer(*this, &WebGLRenderingContext::maybeRestoreContext)
496  , m_generatedImageCache(4)
497  , m_contextLost(false)
498  , m_contextLostMode(SyntheticLostContext)
499  , m_attributes(attributes)
500  , m_synthesizedErrorsToConsole(true)
501  , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
502  , m_isPendingPolicyResolution(false)
503  , m_hasRequestedPolicyResolution(false)
504 {
505  ASSERT(m_context);
506  m_contextGroup = WebGLContextGroup::create();
507  m_contextGroup->addContext(this);
508 
509  m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
510  m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
511 
512  if (m_drawingBuffer)
513  m_drawingBuffer->bind();
514 
515  setupFlags();
516  initializeNewContext();
517 }
518 
519 void WebGLRenderingContext::initializeNewContext()
520 {
521  ASSERT(!m_contextLost);
522  m_needsUpdate = true;
523  m_markedCanvasDirty = false;
524  m_activeTextureUnit = 0;
525  m_packAlignment = 4;
526  m_unpackAlignment = 4;
527  m_unpackFlipY = false;
528  m_unpackPremultiplyAlpha = false;
529  m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
530  m_boundArrayBuffer = 0;
531  m_currentProgram = 0;
532  m_framebufferBinding = 0;
533  m_renderbufferBinding = 0;
534  m_depthMask = true;
535  m_stencilEnabled = false;
536  m_stencilMask = 0xFFFFFFFF;
537  m_stencilMaskBack = 0xFFFFFFFF;
538  m_stencilFuncRef = 0;
539  m_stencilFuncRefBack = 0;
540  m_stencilFuncMask = 0xFFFFFFFF;
541  m_stencilFuncMaskBack = 0xFFFFFFFF;
542  m_layerCleared = false;
543  m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
544 
545  m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
546  m_scissorEnabled = false;
547  m_clearDepth = 1;
548  m_clearStencil = 0;
549  m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
550 
551  GC3Dint numCombinedTextureImageUnits = 0;
552  m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
553  m_textureUnits.clear();
554  m_textureUnits.resize(numCombinedTextureImageUnits);
555 
556  GC3Dint numVertexAttribs = 0;
557  m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
558  m_maxVertexAttribs = numVertexAttribs;
559 
560  m_maxTextureSize = 0;
561  m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
562  m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
563  m_maxCubeMapTextureSize = 0;
564  m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
565  m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
566  m_maxRenderbufferSize = 0;
567  m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
568 
569  // These two values from EXT_draw_buffers are lazily queried.
570  m_maxDrawBuffers = 0;
571  m_maxColorAttachments = 0;
572 
573  m_backDrawBuffer = GraphicsContext3D::BACK;
574  m_drawBuffersWebGLRequirementsChecked = false;
575  m_drawBuffersSupported = false;
576 
577  m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
578  addContextObject(m_defaultVertexArrayObject.get());
579  m_boundVertexArrayObject = m_defaultVertexArrayObject;
580 
581  m_vertexAttribValue.resize(m_maxVertexAttribs);
582 
583  if (!isGLES2NPOTStrict())
584  createFallbackBlackTextures1x1();
585  if (!isGLES2Compliant())
586  initVertexAttrib0();
587 
588  IntSize canvasSize = clampedCanvasSize();
589  if (m_drawingBuffer)
590  m_drawingBuffer->reset(canvasSize);
591 
592  m_context->reshape(canvasSize.width(), canvasSize.height());
593  m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
594  m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
595 
596  m_context->setContextLostCallback(std::make_unique<WebGLRenderingContextLostCallback>(this));
597  m_context->setErrorMessageCallback(std::make_unique<WebGLRenderingContextErrorMessageCallback>(this));
598 }
599 
600 void WebGLRenderingContext::setupFlags()
601 {
602  ASSERT(m_context);
603 
604  if (Page* page = canvas()->document().page())
605  m_synthesizedErrorsToConsole = page->settings().webGLErrorsToConsoleEnabled();
606 
607  m_isGLES2Compliant = m_context->isGLES2Compliant();
608  m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
609  m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
610  if (m_isGLES2Compliant) {
611  m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
612  m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
613  } else {
614  m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
615  m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
616  }
617  m_isRobustnessEXTSupported = m_context->getExtensions()->isEnabled("GL_EXT_robustness");
618 }
619 
620 bool WebGLRenderingContext::allowPrivilegedExtensions() const
621 {
622  if (Page* page = canvas()->document().page())
623  return page->settings().privilegedWebGLExtensionsEnabled();
624  return false;
625 }
626 
627 void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format)
628 {
629  if (!m_compressedTextureFormats.contains(format))
630  m_compressedTextureFormats.append(format);
631 }
632 
633 WebGLRenderingContext::~WebGLRenderingContext()
634 {
635  // Remove all references to WebGLObjects so if they are the last reference
636  // they will be freed before the last context is removed from the context group.
637  m_boundArrayBuffer = nullptr;
638  m_defaultVertexArrayObject = nullptr;
639  m_boundVertexArrayObject = nullptr;
640  m_vertexAttrib0Buffer = nullptr;
641  m_currentProgram = nullptr;
642  m_framebufferBinding = nullptr;
643  m_renderbufferBinding = nullptr;
644 
645  for (size_t i = 0; i < m_textureUnits.size(); ++i) {
646  m_textureUnits[i].texture2DBinding = nullptr;
647  m_textureUnits[i].textureCubeMapBinding = nullptr;
648  }
649 
650  m_blackTexture2D = nullptr;
651  m_blackTextureCubeMap = nullptr;
652 
653  if (!m_isPendingPolicyResolution) {
654  detachAndRemoveAllObjects();
655  destroyGraphicsContext3D();
656  m_contextGroup->removeContext(this);
657  }
658 }
659 
660 void WebGLRenderingContext::destroyGraphicsContext3D()
661 {
662  if (m_isPendingPolicyResolution)
663  return;
664 
665  // The drawing buffer holds a context reference. It must also be destroyed
666  // in order for the context to be released.
667  if (m_drawingBuffer)
668  m_drawingBuffer.clear();
669 
670  if (m_context) {
671  m_context->setContextLostCallback(nullptr);
672  m_context->setErrorMessageCallback(nullptr);
673  m_context.clear();
674  }
675 }
676 
677 void WebGLRenderingContext::markContextChanged()
678 {
679  if (m_framebufferBinding)
680  return;
681 
682  m_context->markContextChanged();
683 
684  if (m_drawingBuffer)
685  m_drawingBuffer->markContentsChanged();
686 
687  m_layerCleared = false;
688  RenderBox* renderBox = canvas()->renderBox();
689  if (isAccelerated() && renderBox && renderBox->hasAcceleratedCompositing()) {
690  m_markedCanvasDirty = true;
691  canvas()->clearCopiedImage();
692  renderBox->contentChanged(CanvasChanged);
693  } else {
694  if (!m_markedCanvasDirty) {
695  m_markedCanvasDirty = true;
696  canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
697  }
698  }
699 }
700 
701 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
702 {
703  if (isContextLostOrPending())
704  return false;
705 
706  if (!m_context->layerComposited() || m_layerCleared
707  || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
708  return false;
709 
710  RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
711 
712  // Determine if it's possible to combine the clear the user asked for and this clear.
713  bool combinedClear = mask && !m_scissorEnabled;
714 
715  m_context->disable(GraphicsContext3D::SCISSOR_TEST);
716  if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
717  m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
718  m_colorMask[1] ? m_clearColor[1] : 0,
719  m_colorMask[2] ? m_clearColor[2] : 0,
720  m_colorMask[3] ? m_clearColor[3] : 0);
721  else
722  m_context->clearColor(0, 0, 0, 0);
723  m_context->colorMask(true, true, true, true);
724  GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
725  if (contextAttributes->depth()) {
726  if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
727  m_context->clearDepth(1.0f);
728  clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
729  m_context->depthMask(true);
730  }
731  if (contextAttributes->stencil()) {
732  if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
733  m_context->clearStencil(m_clearStencil & m_stencilMask);
734  else
735  m_context->clearStencil(0);
736  clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
737  m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
738  }
739  if (m_drawingBuffer)
740  m_drawingBuffer->clearFramebuffers(clearMask);
741  else {
742  if (m_framebufferBinding)
743  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
744  m_context->clear(clearMask);
745  }
746 
747  restoreStateAfterClear();
748  if (m_framebufferBinding)
749  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
750  m_layerCleared = true;
751 
752  return combinedClear;
753 }
754 
755 void WebGLRenderingContext::restoreStateAfterClear()
756 {
757  // Restore the state that the context set.
758  if (m_scissorEnabled)
759  m_context->enable(GraphicsContext3D::SCISSOR_TEST);
760  m_context->clearColor(m_clearColor[0], m_clearColor[1],
761  m_clearColor[2], m_clearColor[3]);
762  m_context->colorMask(m_colorMask[0], m_colorMask[1],
763  m_colorMask[2], m_colorMask[3]);
764  m_context->clearDepth(m_clearDepth);
765  m_context->clearStencil(m_clearStencil);
766  m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
767  m_context->depthMask(m_depthMask);
768 }
769 
770 void WebGLRenderingContext::markLayerComposited()
771 {
772  if (isContextLostOrPending())
773  return;
774  m_context->markLayerComposited();
775 }
776 
777 void WebGLRenderingContext::paintRenderingResultsToCanvas()
778 {
779  if (isContextLostOrPending())
780  return;
781 
782  if (canvas()->document().printing())
783  canvas()->clearPresentationCopy();
784 
785  // Until the canvas is written to by the application, the clear that
786  // happened after it was composited should be ignored by the compositor.
787  if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
788  m_context->paintCompositedResultsToCanvas(canvas()->buffer());
789 
790  canvas()->makePresentationCopy();
791  } else
792  canvas()->clearPresentationCopy();
793  clearIfComposited();
794 
795  if (!m_markedCanvasDirty && !m_layerCleared)
796  return;
797 
798  canvas()->clearCopiedImage();
799  m_markedCanvasDirty = false;
800 
801  if (m_drawingBuffer)
802  m_drawingBuffer->commit();
803  m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get());
804 
805  if (m_drawingBuffer) {
806  if (m_framebufferBinding)
807  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
808  else
809  m_drawingBuffer->bind();
810  }
811 }
812 
813 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
814 {
815  if (isContextLostOrPending())
816  return nullptr;
817  clearIfComposited();
818  if (m_drawingBuffer)
819  m_drawingBuffer->commit();
820  RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
821 
822  if (m_drawingBuffer) {
823  if (m_framebufferBinding)
824  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
825  else
826  m_drawingBuffer->bind();
827  }
828 
829  return imageData;
830 }
831 
832 void WebGLRenderingContext::reshape(int width, int height)
833 {
834  if (isContextLostOrPending())
835  return;
836 
837  // This is an approximation because at WebGLRenderingContext level we don't
838  // know if the underlying FBO uses textures or renderbuffers.
839  GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
840  // Limit drawing buffer size to 4k to avoid memory exhaustion.
841  const int sizeUpperLimit = 4096;
842  maxSize = std::min(maxSize, sizeUpperLimit);
843  GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
844  GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
845  width = clamp(width, 1, maxWidth);
846  height = clamp(height, 1, maxHeight);
847 
848  if (m_needsUpdate) {
849  RenderBox* renderBox = canvas()->renderBox();
850  if (renderBox && renderBox->hasAcceleratedCompositing())
851  renderBox->contentChanged(CanvasChanged);
852  m_needsUpdate = false;
853  }
854 
855  // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
856  // clear (and this matches what reshape will do).
857  if (m_drawingBuffer) {
858  m_drawingBuffer->reset(IntSize(width, height));
859  restoreStateAfterClear();
860  } else
861  m_context->reshape(width, height);
862 
863  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].texture2DBinding.get()));
864  m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get()));
865  if (m_framebufferBinding)
866  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
867 }
868 
869 int WebGLRenderingContext::drawingBufferWidth() const
870 {
871  if (m_drawingBuffer)
872  return m_drawingBuffer->size().width();
873 
874  return m_context->getInternalFramebufferSize().width();
875 }
876 
877 int WebGLRenderingContext::drawingBufferHeight() const
878 {
879  if (m_drawingBuffer)
880  return m_drawingBuffer->size().height();
881 
882  return m_context->getInternalFramebufferSize().height();
883 }
884 
885 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
886 {
887  switch (type) {
888  case GraphicsContext3D::BYTE:
889  return sizeof(GC3Dbyte);
890  case GraphicsContext3D::UNSIGNED_BYTE:
891  return sizeof(GC3Dubyte);
892  case GraphicsContext3D::SHORT:
893  return sizeof(GC3Dshort);
894  case GraphicsContext3D::UNSIGNED_SHORT:
895  return sizeof(GC3Dushort);
896  case GraphicsContext3D::INT:
897  return sizeof(GC3Dint);
898  case GraphicsContext3D::UNSIGNED_INT:
899  return sizeof(GC3Duint);
900  case GraphicsContext3D::FLOAT:
901  return sizeof(GC3Dfloat);
902  }
903  ASSERT_NOT_REACHED();
904  return 0;
905 }
906 
907 void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
908 {
909  UNUSED_PARAM(ec);
910  if (isContextLostOrPending())
911  return;
912  if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
913  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range");
914  return;
915  }
916  m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
917  m_context->activeTexture(texture);
918 
919  if (m_drawingBuffer)
920  m_drawingBuffer->setActiveTextureUnit(texture);
921 }
922 
923 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
924 {
925  UNUSED_PARAM(ec);
926  if (isContextLostOrPending() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader))
927  return;
928  if (!program->attachShader(shader)) {
929  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
930  return;
931  }
932  m_context->attachShader(objectOrZero(program), objectOrZero(shader));
933  shader->onAttached();
934 }
935 
936 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
937 {
938  UNUSED_PARAM(ec);
939  if (isContextLostOrPending() || !validateWebGLObject("bindAttribLocation", program))
940  return;
941  if (!validateLocationLength("bindAttribLocation", name))
942  return;
943  if (!validateString("bindAttribLocation", name))
944  return;
945  if (isPrefixReserved(name)) {
946  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix");
947  return;
948  }
949  if (index >= m_maxVertexAttribs) {
950  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range");
951  return;
952  }
953  m_context->bindAttribLocation(objectOrZero(program), index, name);
954 }
955 
956 bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted)
957 {
958  deleted = false;
959  if (isContextLostOrPending())
960  return false;
961  if (object) {
962  if (!object->validate(contextGroup(), this)) {
963  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context");
964  return false;
965  }
966  deleted = !object->object();
967  }
968  return true;
969 }
970 
971 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
972 {
973  UNUSED_PARAM(ec);
974  bool deleted;
975  if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
976  return;
977  if (deleted)
978  buffer = 0;
979  if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
980  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets");
981  return;
982  }
983  if (target == GraphicsContext3D::ARRAY_BUFFER)
984  m_boundArrayBuffer = buffer;
985  else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
986  m_boundVertexArrayObject->setElementArrayBuffer(buffer);
987  else {
988  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target");
989  return;
990  }
991 
992  m_context->bindBuffer(target, objectOrZero(buffer));
993  if (buffer)
994  buffer->setTarget(target);
995 }
996 
997 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
998 {
999  UNUSED_PARAM(ec);
1000  bool deleted;
1001  if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
1002  return;
1003  if (deleted)
1004  buffer = 0;
1005  if (target != GraphicsContext3D::FRAMEBUFFER) {
1006  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
1007  return;
1008  }
1009  m_framebufferBinding = buffer;
1010  if (m_drawingBuffer)
1011  m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get()));
1012  if (!m_framebufferBinding && m_drawingBuffer) {
1013  // Instead of binding fb 0, bind the drawing buffer.
1014  m_drawingBuffer->bind();
1015  } else
1016  m_context->bindFramebuffer(target, objectOrZero(buffer));
1017  if (buffer)
1018  buffer->setHasEverBeenBound();
1019  applyStencilTest();
1020 }
1021 
1022 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
1023 {
1024  UNUSED_PARAM(ec);
1025  bool deleted;
1026  if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
1027  return;
1028  if (deleted)
1029  renderBuffer = 0;
1030  if (target != GraphicsContext3D::RENDERBUFFER) {
1031  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target");
1032  return;
1033  }
1034  m_renderbufferBinding = renderBuffer;
1035  m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
1036  if (renderBuffer)
1037  renderBuffer->setHasEverBeenBound();
1038 }
1039 
1040 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
1041 {
1042  UNUSED_PARAM(ec);
1043  bool deleted;
1044  if (!checkObjectToBeBound("bindTexture", texture, deleted))
1045  return;
1046  if (deleted)
1047  texture = 0;
1048  if (texture && texture->getTarget() && texture->getTarget() != target) {
1049  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets");
1050  return;
1051  }
1052  GC3Dint maxLevel = 0;
1053  if (target == GraphicsContext3D::TEXTURE_2D) {
1054  m_textureUnits[m_activeTextureUnit].texture2DBinding = texture;
1055  maxLevel = m_maxTextureLevel;
1056 
1057  if (m_drawingBuffer && !m_activeTextureUnit)
1058  m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
1059 
1060  } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
1061  m_textureUnits[m_activeTextureUnit].textureCubeMapBinding = texture;
1062  maxLevel = m_maxCubeMapTextureLevel;
1063  } else {
1064  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target");
1065  return;
1066  }
1067  m_context->bindTexture(target, objectOrZero(texture));
1068  if (texture)
1069  texture->setTarget(target, maxLevel);
1070 
1071  // Note: previously we used to automatically set the TEXTURE_WRAP_R
1072  // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
1073  // ES 2.0 doesn't expose this flag (a bug in the specification) and
1074  // otherwise the application has no control over the seams in this
1075  // dimension. However, it appears that supporting this properly on all
1076  // platforms is fairly involved (will require a HashMap from texture ID
1077  // in all ports), and we have not had any complaints, so the logic has
1078  // been removed.
1079 }
1080 
1081 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
1082 {
1083  if (isContextLostOrPending())
1084  return;
1085  m_context->blendColor(red, green, blue, alpha);
1086 }
1087 
1088 void WebGLRenderingContext::blendEquation(GC3Denum mode)
1089 {
1090  if (isContextLostOrPending() || !validateBlendEquation("blendEquation", mode))
1091  return;
1092  m_context->blendEquation(mode);
1093 }
1094 
1095 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
1096 {
1097  if (isContextLostOrPending() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha))
1098  return;
1099  m_context->blendEquationSeparate(modeRGB, modeAlpha);
1100 }
1101 
1102 
1103 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
1104 {
1105  if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor))
1106  return;
1107  m_context->blendFunc(sfactor, dfactor);
1108 }
1109 
1110 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
1111 {
1112  // Note: Alpha does not have the same restrictions as RGB.
1113  if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB))
1114  return;
1115  m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
1116 }
1117 
1118 void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
1119 {
1120  UNUSED_PARAM(ec);
1121  if (isContextLostOrPending())
1122  return;
1123  WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1124  if (!buffer)
1125  return;
1126  if (size < 0) {
1127  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
1128  return;
1129  }
1130  if (!size) {
1131  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0");
1132  return;
1133  }
1134  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1135  if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
1136  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1137  return;
1138  }
1139  }
1140 
1141  m_context->moveErrorsToSyntheticErrorList();
1142  m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
1143  if (m_context->moveErrorsToSyntheticErrorList()) {
1144  // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
1145  buffer->disassociateBufferData();
1146  }
1147 }
1148 
1149 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
1150 {
1151  UNUSED_PARAM(ec);
1152  if (isContextLostOrPending())
1153  return;
1154  WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1155  if (!buffer)
1156  return;
1157  if (!data) {
1158  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1159  return;
1160  }
1161  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1162  if (!buffer->associateBufferData(data)) {
1163  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1164  return;
1165  }
1166  }
1167 
1168  m_context->moveErrorsToSyntheticErrorList();
1169  m_context->bufferData(target, data->byteLength(), data->data(), usage);
1170  if (m_context->moveErrorsToSyntheticErrorList()) {
1171  // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
1172  buffer->disassociateBufferData();
1173  }
1174 }
1175 
1176 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
1177 {
1178  UNUSED_PARAM(ec);
1179  if (isContextLostOrPending())
1180  return;
1181  WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1182  if (!buffer)
1183  return;
1184  if (!data) {
1185  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1186  return;
1187  }
1188  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1189  if (!buffer->associateBufferData(data)) {
1190  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1191  return;
1192  }
1193  }
1194 
1195  m_context->moveErrorsToSyntheticErrorList();
1196  m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
1197  if (m_context->moveErrorsToSyntheticErrorList()) {
1198  // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
1199  buffer->disassociateBufferData();
1200  }
1201 }
1202 
1203 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
1204 {
1205  UNUSED_PARAM(ec);
1206  if (isContextLostOrPending())
1207  return;
1208  WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1209  if (!buffer)
1210  return;
1211  if (offset < 0) {
1212  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1213  return;
1214  }
1215  if (!data)
1216  return;
1217  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1218  if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1219  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1220  return;
1221  }
1222  }
1223 
1224  m_context->moveErrorsToSyntheticErrorList();
1225  m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
1226  if (m_context->moveErrorsToSyntheticErrorList()) {
1227  // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
1228  buffer->disassociateBufferData();
1229  }
1230 }
1231 
1232 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
1233 {
1234  UNUSED_PARAM(ec);
1235  if (isContextLostOrPending())
1236  return;
1237  WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1238  if (!buffer)
1239  return;
1240  if (offset < 0) {
1241  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1242  return;
1243  }
1244  if (!data)
1245  return;
1246  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1247  if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1248  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1249  return;
1250  }
1251  }
1252 
1253  m_context->moveErrorsToSyntheticErrorList();
1254  m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
1255  if (m_context->moveErrorsToSyntheticErrorList()) {
1256  // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
1257  buffer->disassociateBufferData();
1258  }
1259 }
1260 
1261 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
1262 {
1263  if (isContextLostOrPending())
1264  return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
1265  if (target != GraphicsContext3D::FRAMEBUFFER) {
1266  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
1267  return 0;
1268  }
1269  if (!m_framebufferBinding || !m_framebufferBinding->object())
1270  return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
1271  const char* reason = "framebuffer incomplete";
1272  GC3Denum result = m_framebufferBinding->checkStatus(&reason);
1273  if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1274  printGLWarningToConsole("checkFramebufferStatus", reason);
1275  return result;
1276  }
1277  result = m_context->checkFramebufferStatus(target);
1278  return result;
1279 }
1280 
1281 void WebGLRenderingContext::clear(GC3Dbitfield mask)
1282 {
1283  if (isContextLostOrPending())
1284  return;
1285  if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1286  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
1287  return;
1288  }
1289  const char* reason = "framebuffer incomplete";
1290  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1291  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
1292  return;
1293  }
1294  if (!clearIfComposited(mask))
1295  m_context->clear(mask);
1296  markContextChanged();
1297 }
1298 
1299 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
1300 {
1301  if (isContextLostOrPending())
1302  return;
1303  if (std::isnan(r))
1304  r = 0;
1305  if (std::isnan(g))
1306  g = 0;
1307  if (std::isnan(b))
1308  b = 0;
1309  if (std::isnan(a))
1310  a = 1;
1311  m_clearColor[0] = r;
1312  m_clearColor[1] = g;
1313  m_clearColor[2] = b;
1314  m_clearColor[3] = a;
1315  m_context->clearColor(r, g, b, a);
1316 }
1317 
1318 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
1319 {
1320  if (isContextLostOrPending())
1321  return;
1322  m_clearDepth = depth;
1323  m_context->clearDepth(depth);
1324 }
1325 
1326 void WebGLRenderingContext::clearStencil(GC3Dint s)
1327 {
1328  if (isContextLostOrPending())
1329  return;
1330  m_clearStencil = s;
1331  m_context->clearStencil(s);
1332 }
1333 
1334 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
1335 {
1336  if (isContextLostOrPending())
1337  return;
1338  m_colorMask[0] = red;
1339  m_colorMask[1] = green;
1340  m_colorMask[2] = blue;
1341  m_colorMask[3] = alpha;
1342  m_context->colorMask(red, green, blue, alpha);
1343 }
1344 
1345 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
1346 {
1347  UNUSED_PARAM(ec);
1348  if (isContextLostOrPending() || !validateWebGLObject("compileShader", shader))
1349  return;
1350  m_context->compileShader(objectOrZero(shader));
1351  GC3Dint value;
1352  m_context->getShaderiv(objectOrZero(shader), GraphicsContext3D::COMPILE_STATUS, &value);
1353  shader->setValid(value);
1354 }
1355 
1356 void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
1357  GC3Dsizei height, GC3Dint border, ArrayBufferView* data)
1358 {
1359  if (isContextLostOrPending())
1360  return;
1361  if (!validateTexFuncLevel("compressedTexImage2D", target, level))
1362  return;
1363 
1364  if (!validateCompressedTexFormat(internalformat)) {
1365  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat");
1366  return;
1367  }
1368  if (border) {
1369  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0");
1370  return;
1371  }
1372  if (!validateCompressedTexDimensions("compressedTexImage2D", target, level, width, height, internalformat))
1373  return;
1374  if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data))
1375  return;
1376 
1377  WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true);
1378  if (!tex)
1379  return;
1380  if (!isGLES2NPOTStrict()) {
1381  if (level && WebGLTexture::isNPOT(width, height)) {
1382  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2");
1383  return;
1384  }
1385  }
1386  m_context->moveErrorsToSyntheticErrorList();
1387  m_context->compressedTexImage2D(target, level, internalformat, width, height,
1388  border, data->byteLength(), data->baseAddress());
1389  if (m_context->moveErrorsToSyntheticErrorList()) {
1390  // The compressedTexImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
1391  tex->markInvalid(target, level);
1392  return;
1393  }
1394 
1395  tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1396  tex->setCompressed();
1397 }
1398 
1399 void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
1400  GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data)
1401 {
1402  if (isContextLostOrPending())
1403  return;
1404  if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
1405  return;
1406  if (!validateCompressedTexFormat(format)) {
1407  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format");
1408  return;
1409  }
1410  if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
1411  return;
1412 
1413  WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true);
1414  if (!tex)
1415  return;
1416 
1417  if (format != tex->getInternalFormat(target, level)) {
1418  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format");
1419  return;
1420  }
1421 
1422  if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex))
1423  return;
1424 
1425  graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset,
1426  width, height, format, data->byteLength(), data->baseAddress());
1427  tex->setCompressed();
1428 }
1429 
1430 bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format)
1431 {
1432  if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1433  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
1434  return false;
1435  }
1436  return true;
1437 }
1438 
1439 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
1440 {
1441  if (isContextLostOrPending())
1442  return;
1443  if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
1444  return;
1445  if (!validateSettableTexFormat("copyTexImage2D", internalformat))
1446  return;
1447  WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
1448  if (!tex)
1449  return;
1450  if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1451  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
1452  return;
1453  }
1454  if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1455  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
1456  return;
1457  }
1458  const char* reason = "framebuffer incomplete";
1459  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1460  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
1461  return;
1462  }
1463  clearIfComposited();
1464  if (isResourceSafe()) {
1465  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1466  m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1467  } else {
1468  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1469  GC3Dint clippedX, clippedY;
1470  GC3Dsizei clippedWidth, clippedHeight;
1471  if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1472  m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
1473  internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
1474  if (clippedWidth > 0 && clippedHeight > 0) {
1475  m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
1476  clippedX, clippedY, clippedWidth, clippedHeight);
1477  }
1478  } else
1479  m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1480  }
1481  // FIXME: if the framebuffer is not complete, none of the below should be executed.
1482  tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1483 }
1484 
1485 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1486 {
1487  if (isContextLostOrPending())
1488  return;
1489  if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
1490  return;
1491  WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true);
1492  if (!tex)
1493  return;
1494  if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height))
1495  return;
1496  // Before checking if it is in the range, check if overflow happens first.
1497  if (xoffset + width < 0 || yoffset + height < 0) {
1498  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions");
1499  return;
1500  }
1501  if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
1502  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
1503  return;
1504  }
1505  GC3Denum internalformat = tex->getInternalFormat(target, level);
1506  if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
1507  return;
1508  if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1509  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
1510  return;
1511  }
1512  const char* reason = "framebuffer incomplete";
1513  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1514  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
1515  return;
1516  }
1517  clearIfComposited();
1518  if (isResourceSafe()) {
1519  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1520  m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1521  } else {
1522  GC3Dint clippedX, clippedY;
1523  GC3Dsizei clippedWidth, clippedHeight;
1524  if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1525  GC3Denum format = tex->getInternalFormat(target, level);
1526  GC3Denum type = tex->getType(target, level);
1527  std::unique_ptr<unsigned char[]> zero;
1528  if (width && height) {
1529  unsigned int size;
1530  GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
1531  if (error != GraphicsContext3D::NO_ERROR) {
1532  synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
1533  return;
1534  }
1535  zero = std::make_unique<unsigned char[]>(size);
1536  if (!zero) {
1537  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory");
1538  return;
1539  }
1540  memset(zero.get(), 0, size);
1541  }
1542  m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
1543  if (clippedWidth > 0 && clippedHeight > 0) {
1544  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1545  m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
1546  clippedX, clippedY, clippedWidth, clippedHeight);
1547  }
1548  } else {
1549  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1550  m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1551  }
1552  }
1553 }
1554 
1555 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1556 {
1557  if (isContextLostOrPending())
1558  return nullptr;
1559  RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1560  addSharedObject(o.get());
1561  return o;
1562 }
1563 
1564 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1565 {
1566  if (isContextLostOrPending())
1567  return nullptr;
1568  RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1569  addContextObject(o.get());
1570  return o;
1571 }
1572 
1573 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1574 {
1575  if (isContextLostOrPending())
1576  return nullptr;
1577  RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1578  addSharedObject(o.get());
1579  return o;
1580 }
1581 
1582 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1583 {
1584  if (isContextLostOrPending())
1585  return nullptr;
1586  RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1587  addSharedObject(o.get());
1588  return o;
1589 }
1590 
1591 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1592 {
1593  if (isContextLostOrPending())
1594  return nullptr;
1595  RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1596  addSharedObject(o.get());
1597  return o;
1598 }
1599 
1600 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
1601 {
1602  UNUSED_PARAM(ec);
1603  if (isContextLostOrPending())
1604  return nullptr;
1605  if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
1606  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type");
1607  return nullptr;
1608  }
1609 
1610  RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1611  addSharedObject(o.get());
1612  return o;
1613 }
1614 
1615 void WebGLRenderingContext::cullFace(GC3Denum mode)
1616 {
1617  if (isContextLostOrPending())
1618  return;
1619  m_context->cullFace(mode);
1620 }
1621 
1622 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1623 {
1624  if (isContextLostOrPending() || !object)
1625  return false;
1626  if (!object->validate(contextGroup(), this)) {
1627  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context");
1628  return false;
1629  }
1630  if (object->object())
1631  // We need to pass in context here because we want
1632  // things in this context unbound.
1633  object->deleteObject(graphicsContext3D());
1634  return true;
1635 }
1636 
1637 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1638 {
1639  if (!deleteObject(buffer))
1640  return;
1641  if (m_boundArrayBuffer == buffer)
1642  m_boundArrayBuffer = 0;
1643 
1644  m_boundVertexArrayObject->unbindBuffer(buffer);
1645 }
1646 
1647 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1648 {
1649  if (!deleteObject(framebuffer))
1650  return;
1651  if (framebuffer == m_framebufferBinding) {
1652  m_framebufferBinding = 0;
1653  if (m_drawingBuffer) {
1654  m_drawingBuffer->setFramebufferBinding(0);
1655  // Have to call bindFramebuffer here to bind back to internal fbo.
1656  m_drawingBuffer->bind();
1657  } else
1658  m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
1659  }
1660 }
1661 
1662 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1663 {
1664  deleteObject(program);
1665  // We don't reset m_currentProgram to 0 here because the deletion of the
1666  // current program is delayed.
1667 }
1668 
1669 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1670 {
1671  if (!deleteObject(renderbuffer))
1672  return;
1673  if (renderbuffer == m_renderbufferBinding)
1674  m_renderbufferBinding = 0;
1675  if (m_framebufferBinding)
1676  m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
1677 }
1678 
1679 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1680 {
1681  deleteObject(shader);
1682 }
1683 
1684 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1685 {
1686  if (!deleteObject(texture))
1687  return;
1688  for (size_t i = 0; i < m_textureUnits.size(); ++i) {
1689  if (texture == m_textureUnits[i].texture2DBinding)
1690  m_textureUnits[i].texture2DBinding = nullptr;
1691  if (texture == m_textureUnits[i].textureCubeMapBinding)
1692  m_textureUnits[i].textureCubeMapBinding = nullptr;
1693  }
1694  if (m_framebufferBinding)
1695  m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
1696 }
1697 
1698 void WebGLRenderingContext::depthFunc(GC3Denum func)
1699 {
1700  if (isContextLostOrPending())
1701  return;
1702  m_context->depthFunc(func);
1703 }
1704 
1705 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1706 {
1707  if (isContextLostOrPending())
1708  return;
1709  m_depthMask = flag;
1710  m_context->depthMask(flag);
1711 }
1712 
1713 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1714 {
1715  if (isContextLostOrPending())
1716  return;
1717  if (zNear > zFar) {
1718  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar");
1719  return;
1720  }
1721  m_context->depthRange(zNear, zFar);
1722 }
1723 
1724 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
1725 {
1726  UNUSED_PARAM(ec);
1727  if (isContextLostOrPending() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader))
1728  return;
1729  if (!program->detachShader(shader)) {
1730  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
1731  return;
1732  }
1733  m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1734  shader->onDetached(graphicsContext3D());
1735 }
1736 
1737 void WebGLRenderingContext::disable(GC3Denum cap)
1738 {
1739  if (isContextLostOrPending() || !validateCapability("disable", cap))
1740  return;
1741  if (cap == GraphicsContext3D::STENCIL_TEST) {
1742  m_stencilEnabled = false;
1743  applyStencilTest();
1744  return;
1745  }
1746  if (cap == GraphicsContext3D::SCISSOR_TEST) {
1747  m_scissorEnabled = false;
1748  if (m_drawingBuffer)
1749  m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
1750  }
1751  m_context->disable(cap);
1752 }
1753 
1754 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1755 {
1756  UNUSED_PARAM(ec);
1757  if (isContextLostOrPending())
1758  return;
1759  if (index >= m_maxVertexAttribs) {
1760  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range");
1761  return;
1762  }
1763 
1764  WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1765  state.enabled = false;
1766 
1767  if (index > 0 || isGLES2Compliant())
1768  m_context->disableVertexAttribArray(index);
1769 }
1770 
1771 bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
1772 {
1773  RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1774 
1775  if (!elementArrayBuffer)
1776  return false;
1777 
1778  if (offset < 0)
1779  return false;
1780 
1781  if (type == GraphicsContext3D::UNSIGNED_INT) {
1782  // For an unsigned int array, offset must be divisible by 4 for alignment reasons.
1783  if (offset % 4)
1784  return false;
1785 
1786  // Make uoffset an element offset.
1787  offset /= 4;
1788 
1789  GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 4;
1790  if (offset > n || count > n - offset)
1791  return false;
1792  } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1793  // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1794  if (offset % 2)
1795  return false;
1796 
1797  // Make uoffset an element offset.
1798  offset /= 2;
1799 
1800  GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
1801  if (offset > n || count > n - offset)
1802  return false;
1803  } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1804  GC3Dsizeiptr n = elementArrayBuffer->byteLength();
1805  if (offset > n || count > n - offset)
1806  return false;
1807  }
1808  return true;
1809 }
1810 
1811 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
1812 {
1813  // Performs conservative validation by caching a maximum index of
1814  // the given type per element array buffer. If all of the bound
1815  // array buffers have enough elements to satisfy that maximum
1816  // index, skips the expensive per-draw-call iteration in
1817  // validateIndexArrayPrecise.
1818 
1819  RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1820 
1821  if (!elementArrayBuffer)
1822  return false;
1823 
1824  GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1825  // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1826  if (!numElements)
1827  return false;
1828  const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1829  ASSERT(buffer);
1830 
1831  int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1832  if (maxIndex < 0) {
1833  // Compute the maximum index in the entire buffer for the given type of index.
1834  switch (type) {
1835  case GraphicsContext3D::UNSIGNED_BYTE: {
1836  const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1837  for (GC3Dsizeiptr i = 0; i < numElements; i++)
1838  maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1839  break;
1840  }
1841  case GraphicsContext3D::UNSIGNED_SHORT: {
1842  numElements /= sizeof(GC3Dushort);
1843  const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1844  for (GC3Dsizeiptr i = 0; i < numElements; i++)
1845  maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1846  break;
1847  }
1848  case GraphicsContext3D::UNSIGNED_INT: {
1849  if (!m_oesElementIndexUint)
1850  return false;
1851  numElements /= sizeof(GC3Duint);
1852  const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
1853  for (GC3Dsizeiptr i = 0; i < numElements; i++)
1854  maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1855  break;
1856  }
1857  default:
1858  return false;
1859  }
1860  elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1861  }
1862 
1863  if (maxIndex >= 0) {
1864  // The number of required elements is one more than the maximum
1865  // index that will be accessed.
1866  numElementsRequired = maxIndex + 1;
1867  return true;
1868  }
1869 
1870  return false;
1871 }
1872 
1873 bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired)
1874 {
1875  ASSERT(count >= 0 && offset >= 0);
1876  unsigned lastIndex = 0;
1877 
1878  RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1879 
1880  if (!elementArrayBuffer)
1881  return false;
1882 
1883  if (!count) {
1884  numElementsRequired = 0;
1885  return true;
1886  }
1887 
1888  if (!elementArrayBuffer->elementArrayBuffer())
1889  return false;
1890 
1891  unsigned long uoffset = offset;
1892  unsigned long n = count;
1893 
1894  if (type == GraphicsContext3D::UNSIGNED_INT) {
1895  // Make uoffset an element offset.
1896  uoffset /= sizeof(GC3Duint);
1897  const GC3Duint* p = static_cast<const GC3Duint*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1898  while (n-- > 0) {
1899  if (*p > lastIndex)
1900  lastIndex = *p;
1901  ++p;
1902  }
1903  } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1904  // Make uoffset an element offset.
1905  uoffset /= sizeof(GC3Dushort);
1906  const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1907  while (n-- > 0) {
1908  if (*p > lastIndex)
1909  lastIndex = *p;
1910  ++p;
1911  }
1912  } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1913  const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1914  while (n-- > 0) {
1915  if (*p > lastIndex)
1916  lastIndex = *p;
1917  ++p;
1918  }
1919  }
1920 
1921  // Then set the last index in the index array and make sure it is valid.
1922  numElementsRequired = lastIndex + 1;
1923  return numElementsRequired > 0;
1924 }
1925 
1926 bool WebGLRenderingContext::validateVertexAttributes(unsigned elementCount, unsigned primitiveCount)
1927 {
1928  if (!m_currentProgram)
1929  return false;
1930 
1931  // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1932  for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
1933  if (!m_boundVertexArrayObject->getVertexAttribState(i).validateBinding())
1934  return false;
1935  }
1936 
1937  if (elementCount <= 0)
1938  return true;
1939 
1940 
1941  // Look in each consumed vertex attrib (by the current program).
1942  bool sawNonInstancedAttrib = false;
1943  bool sawEnabledAttrib = false;
1944  int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1945  for (int i = 0; i < numActiveAttribLocations; ++i) {
1946  int loc = m_currentProgram->getActiveAttribLocation(i);
1947  if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
1948  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
1949  if (state.enabled) {
1950  sawEnabledAttrib = true;
1951  // Avoid off-by-one errors in numElements computation.
1952  // For the last element, we will only touch the data for the
1953  // element and nothing beyond it.
1954  int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
1955  unsigned numElements = 0;
1956  ASSERT(state.stride > 0);
1957  if (bytesRemaining >= state.bytesPerElement)
1958  numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1959  unsigned instancesRequired = 0;
1960  if (state.divisor) {
1961  instancesRequired = ceil(static_cast<float>(primitiveCount) / state.divisor);
1962  if (instancesRequired > numElements)
1963  return false;
1964  } else {
1965  sawNonInstancedAttrib = true;
1966  if (elementCount > numElements)
1967  return false;
1968  }
1969  }
1970  }
1971  }
1972 
1973  if (!sawNonInstancedAttrib && sawEnabledAttrib)
1974  return false;
1975 
1976  return true;
1977 }
1978 
1979 bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object)
1980 {
1981  if (!object || !object->object()) {
1982  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted");
1983  return false;
1984  }
1985  if (!object->validate(contextGroup(), this)) {
1986  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context");
1987  return false;
1988  }
1989  return true;
1990 }
1991 
1992 bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primitiveCount)
1993 {
1994  if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
1995  return false;
1996 
1997  if (!validateStencilSettings(functionName))
1998  return false;
1999 
2000  if (first < 0 || count < 0) {
2001  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0");
2002  return false;
2003  }
2004 
2005  if (!count) {
2006  markContextChanged();
2007  return false;
2008  }
2009 
2010  if (primitiveCount < 0) {
2011  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
2012  return false;
2013  }
2014 
2015  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
2016  // Ensure we have a valid rendering state
2017  Checked<GC3Dint, RecordOverflow> checkedFirst(first);
2018  Checked<GC3Dint, RecordOverflow> checkedCount(count);
2019  Checked<GC3Dint, RecordOverflow> checkedSum = checkedFirst + checkedCount;
2020  Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount);
2021  if (checkedSum.hasOverflowed() || checkedPrimitiveCount.hasOverflowed() || !validateVertexAttributes(checkedSum.unsafeGet(), checkedPrimitiveCount.unsafeGet())) {
2022  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
2023  return false;
2024  }
2025  } else {
2026  if (!validateVertexAttributes(0)) {
2027  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
2028  return false;
2029  }
2030  }
2031 
2032  const char* reason = "framebuffer incomplete";
2033  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
2034  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
2035  return false;
2036  }
2037 
2038  return true;
2039 }
2040 
2041 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
2042 {
2043  UNUSED_PARAM(ec);
2044 
2045  if (!validateDrawArrays("drawArrays", mode, first, count, 0))
2046  return;
2047 
2048  clearIfComposited();
2049 
2050  bool vertexAttrib0Simulated = false;
2051  if (!isGLES2Compliant())
2052  vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
2053  if (!isGLES2NPOTStrict())
2054  checkTextureCompleteness("drawArrays", true);
2055 
2056  m_context->drawArrays(mode, first, count);
2057 
2058  if (!isGLES2Compliant() && vertexAttrib0Simulated)
2059  restoreStatesAfterVertexAttrib0Simulation();
2060  if (!isGLES2NPOTStrict())
2061  checkTextureCompleteness("drawArrays", false);
2062  markContextChanged();
2063 }
2064 
2065 bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primitiveCount)
2066 {
2067  if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
2068  return false;
2069 
2070  if (!validateStencilSettings(functionName))
2071  return false;
2072 
2073  switch (type) {
2074  case GraphicsContext3D::UNSIGNED_BYTE:
2075  case GraphicsContext3D::UNSIGNED_SHORT:
2076  break;
2077  case GraphicsContext3D::UNSIGNED_INT:
2078  if (m_oesElementIndexUint)
2079  break;
2080  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
2081  return false;
2082  default:
2083  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
2084  return false;
2085  }
2086 
2087  if (count < 0 || offset < 0) {
2088  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0");
2089  return false;
2090  }
2091 
2092  if (!count) {
2093  markContextChanged();
2094  return false;
2095  }
2096 
2097  if (primitiveCount < 0) {
2098  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
2099  return false;
2100  }
2101 
2102  if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
2103  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound");
2104  return false;
2105  }
2106 
2107  if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
2108  // Ensure we have a valid rendering state
2109  if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
2110  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "request out of bounds for current ELEMENT_ARRAY_BUFFER");
2111  return false;
2112  }
2113  if (!count)
2114  return false;
2115 
2116  Checked<GC3Dint, RecordOverflow> checkedCount(count);
2117  Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount);
2118  if (checkedCount.hasOverflowed() || checkedPrimitiveCount.hasOverflowed()) {
2119  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
2120  return false;
2121  }
2122 
2123  if (!validateIndexArrayConservative(type, numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) {
2124  if (!validateIndexArrayPrecise(checkedCount.unsafeGet(), type, static_cast<GC3Dintptr>(offset), numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) {
2125  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
2126  return false;
2127  }
2128  }
2129  } else {
2130  if (!validateVertexAttributes(0)) {
2131  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
2132  return false;
2133  }
2134  }
2135 
2136  const char* reason = "framebuffer incomplete";
2137  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
2138  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
2139  return false;
2140  }
2141 
2142  return true;
2143 }
2144 
2145 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
2146 {
2147  UNUSED_PARAM(ec);
2148 
2149  unsigned numElements = 0;
2150  if (!validateDrawElements("drawElements", mode, count, type, offset, numElements, 0))
2151  return;
2152 
2153  clearIfComposited();
2154 
2155  bool vertexAttrib0Simulated = false;
2156  if (!isGLES2Compliant()) {
2157  if (!numElements)
2158  validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
2159  vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
2160  }
2161  if (!isGLES2NPOTStrict())
2162  checkTextureCompleteness("drawElements", true);
2163 
2164  m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
2165 
2166  if (!isGLES2Compliant() && vertexAttrib0Simulated)
2167  restoreStatesAfterVertexAttrib0Simulation();
2168  if (!isGLES2NPOTStrict())
2169  checkTextureCompleteness("drawElements", false);
2170  markContextChanged();
2171 }
2172 
2173 void WebGLRenderingContext::enable(GC3Denum cap)
2174 {
2175  if (isContextLostOrPending() || !validateCapability("enable", cap))
2176  return;
2177  if (cap == GraphicsContext3D::STENCIL_TEST) {
2178  m_stencilEnabled = true;
2179  applyStencilTest();
2180  return;
2181  }
2182  if (cap == GraphicsContext3D::SCISSOR_TEST) {
2183  m_scissorEnabled = true;
2184  if (m_drawingBuffer)
2185  m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
2186  }
2187  m_context->enable(cap);
2188 }
2189 
2190 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
2191 {
2192  UNUSED_PARAM(ec);
2193  if (isContextLostOrPending())
2194  return;
2195  if (index >= m_maxVertexAttribs) {
2196  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range");
2197  return;
2198  }
2199 
2200  WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
2201  state.enabled = true;
2202 
2203  m_context->enableVertexAttribArray(index);
2204 }
2205 
2206 void WebGLRenderingContext::finish()
2207 {
2208  if (isContextLostOrPending())
2209  return;
2210  m_context->finish();
2211 }
2212 
2213 void WebGLRenderingContext::flush()
2214 {
2215  if (isContextLostOrPending())
2216  return;
2217  m_context->flush();
2218 }
2219 
2220 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
2221 {
2222  UNUSED_PARAM(ec);
2223  if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment))
2224  return;
2225  if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
2226  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target");
2227  return;
2228  }
2229  if (buffer && !buffer->validate(contextGroup(), this)) {
2230  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
2231  return;
2232  }
2233  // Don't allow the default framebuffer to be mutated; all current
2234  // implementations use an FBO internally in place of the default
2235  // FBO.
2236  if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2237  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
2238  return;
2239  }
2240  Platform3DObject bufferObject = objectOrZero(buffer);
2241  switch (attachment) {
2242  case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2243  m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
2244  m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
2245  break;
2246  default:
2247  m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2248  }
2249  m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
2250  applyStencilTest();
2251 }
2252 
2253 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
2254 {
2255  UNUSED_PARAM(ec);
2256  if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
2257  return;
2258  if (level) {
2259  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
2260  return;
2261  }
2262  if (texture && !texture->validate(contextGroup(), this)) {
2263  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
2264  return;
2265  }
2266  // Don't allow the default framebuffer to be mutated; all current
2267  // implementations use an FBO internally in place of the default
2268  // FBO.
2269  if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2270  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
2271  return;
2272  }
2273  Platform3DObject textureObject = objectOrZero(texture);
2274  switch (attachment) {
2275  case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2276  m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level);
2277  m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level);
2278  break;
2279  case GraphicsContext3D::DEPTH_ATTACHMENT:
2280  m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2281  break;
2282  case GraphicsContext3D::STENCIL_ATTACHMENT:
2283  m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2284  break;
2285  default:
2286  m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2287  }
2288  m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
2289  applyStencilTest();
2290 }
2291 
2292 void WebGLRenderingContext::frontFace(GC3Denum mode)
2293 {
2294  if (isContextLostOrPending())
2295  return;
2296  m_context->frontFace(mode);
2297 }
2298 
2299 void WebGLRenderingContext::generateMipmap(GC3Denum target)
2300 {
2301  if (isContextLostOrPending())
2302  return;
2303  WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
2304  if (!tex)
2305  return;
2306  if (!tex->canGenerateMipmaps()) {
2307  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size");
2308  return;
2309  }
2310  // FIXME: https://bugs.webkit.org/show_bug.cgi?id=123916. Compressed textures should be allowed in WebGL 2:
2311  if (tex->isCompressed()) {
2312  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture");
2313  return;
2314  }
2315  if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
2316  return;
2317 
2318  // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
2319  // on Mac. Remove the hack once this driver bug is fixed.
2320 #if OS(DARWIN)
2321  bool needToResetMinFilter = false;
2322  if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
2323  m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
2324  needToResetMinFilter = true;
2325  }
2326 #endif
2327  m_context->generateMipmap(target);
2328 #if OS(DARWIN)
2329  if (needToResetMinFilter)
2330  m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
2331 #endif
2332  tex->generateMipmapLevelInfo();
2333 }
2334 
2335 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2336 {
2337  UNUSED_PARAM(ec);
2338  if (isContextLostOrPending() || !validateWebGLObject("getActiveAttrib", program))
2339  return nullptr;
2340  ActiveInfo info;
2341  if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
2342  return nullptr;
2343 
2344  LOG(WebGL, "Returning active attribute %d: %s", index, info.name.utf8().data());
2345 
2346  return WebGLActiveInfo::create(info.name, info.type, info.size);
2347 }
2348 
2349 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2350 {
2351  UNUSED_PARAM(ec);
2352  if (isContextLostOrPending() || !validateWebGLObject("getActiveUniform", program))
2353  return 0;
2354  ActiveInfo info;
2355  if (!m_context->getActiveUniform(objectOrZero(program), index, info))
2356  return nullptr;
2357  if (!isGLES2Compliant())
2358  if (info.size > 1 && !info.name.endsWith("[0]"))
2359  info.name.append("[0]");
2360 
2361  LOG(WebGL, "Returning active uniform %d: %s", index, info.name.utf8().data());
2362 
2363  return WebGLActiveInfo::create(info.name, info.type, info.size);
2364 }
2365 
2366 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader>>& shaderObjects, ExceptionCode& ec)
2367 {
2368  UNUSED_PARAM(ec);
2369  shaderObjects.clear();
2370  if (isContextLostOrPending() || !validateWebGLObject("getAttachedShaders", program))
2371  return false;
2372 
2373  const GC3Denum shaderType[] = {
2374  GraphicsContext3D::VERTEX_SHADER,
2375  GraphicsContext3D::FRAGMENT_SHADER
2376  };
2377  for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
2378  WebGLShader* shader = program->getAttachedShader(shaderType[i]);
2379  if (shader)
2380  shaderObjects.append(shader);
2381  }
2382  return true;
2383 }
2384 
2385 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
2386 {
2387  if (isContextLostOrPending() || !validateWebGLObject("getAttribLocation", program))
2388  return -1;
2389  if (!validateLocationLength("getAttribLocation", name))
2390  return -1;
2391  if (!validateString("getAttribLocation", name))
2392  return -1;
2393  if (isPrefixReserved(name))
2394  return -1;
2395  if (!program->getLinkStatus()) {
2396  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked");
2397  return -1;
2398  }
2399  return m_context->getAttribLocation(objectOrZero(program), name);
2400 }
2401 
2402 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2403 {
2404  UNUSED_PARAM(ec);
2405  if (isContextLostOrPending())
2406  return WebGLGetInfo();
2407  if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
2408  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
2409  return WebGLGetInfo();
2410  }
2411 
2412  if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
2413  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
2414  return WebGLGetInfo();
2415  }
2416 
2417  GC3Dint value = 0;
2418  m_context->getBufferParameteriv(target, pname, &value);
2419  if (pname == GraphicsContext3D::BUFFER_SIZE)
2420  return WebGLGetInfo(value);
2421  return WebGLGetInfo(static_cast<unsigned int>(value));
2422 }
2423 
2424 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
2425 {
2426  if (isContextLostOrPending())
2427  return nullptr;
2428  // We always need to return a new WebGLContextAttributes object to
2429  // prevent the user from mutating any cached version.
2430 
2431  // Also, we need to enforce requested values of "false" for depth
2432  // and stencil, regardless of the properties of the underlying
2433  // GraphicsContext3D or DrawingBuffer.
2434  RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
2435  if (!m_attributes.depth)
2436  attributes->setDepth(false);
2437  if (!m_attributes.stencil)
2438  attributes->setStencil(false);
2439  if (m_drawingBuffer) {
2440  // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(),
2441  // but it makes its own determination of whether multisampling is supported.
2442  attributes->setAntialias(m_drawingBuffer->multisample());
2443  }
2444  return attributes.release();
2445 }
2446 
2447 GC3Denum WebGLRenderingContext::getError()
2448 {
2449  if (m_isPendingPolicyResolution)
2450  return GraphicsContext3D::NO_ERROR;
2451  return m_context->getError();
2452 }
2453 
2454 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
2455 {
2456  if (isContextLostOrPending())
2457  return nullptr;
2458 
2459  if (equalIgnoringCase(name, "EXT_blend_minmax")
2460  && m_context->getExtensions()->supports("GL_EXT_blend_minmax")) {
2461  if (!m_extBlendMinMax) {
2462  m_context->getExtensions()->ensureEnabled("GL_EXT_blend_minmax");
2463  m_extBlendMinMax = std::make_unique<EXTBlendMinMax>(this);
2464  }
2465  return m_extBlendMinMax.get();
2466  }
2467  if (equalIgnoringCase(name, "EXT_sRGB")
2468  && m_context->getExtensions()->supports("GL_EXT_sRGB")) {
2469  if (!m_extsRGB) {
2470  m_context->getExtensions()->ensureEnabled("GL_EXT_sRGB");
2471  m_extsRGB = std::make_unique<EXTsRGB>(this);
2472  }
2473  return m_extsRGB.get();
2474  }
2475  if (equalIgnoringCase(name, "EXT_frag_depth")
2476  && m_context->getExtensions()->supports("GL_EXT_frag_depth")) {
2477  if (!m_extFragDepth) {
2478  m_context->getExtensions()->ensureEnabled("GL_EXT_frag_depth");
2479  m_extFragDepth = std::make_unique<EXTFragDepth>(this);
2480  }
2481  return m_extFragDepth.get();
2482  }
2483  if (equalIgnoringCase(name, "EXT_shader_texture_lod")
2484  && (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))) {
2485  if (!m_extShaderTextureLOD) {
2486  m_context->getExtensions()->ensureEnabled("GL_EXT_shader_texture_lod");
2487  m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(this);
2488  }
2489  return m_extShaderTextureLOD.get();
2490  }
2491  if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic")
2492  && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
2493  if (!m_extTextureFilterAnisotropic) {
2494  m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
2495  m_extTextureFilterAnisotropic = std::make_unique<EXTTextureFilterAnisotropic>(this);
2496  }
2497  return m_extTextureFilterAnisotropic.get();
2498  }
2499  if (equalIgnoringCase(name, "OES_standard_derivatives")
2500  && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
2501  if (!m_oesStandardDerivatives) {
2502  m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
2503  m_oesStandardDerivatives = std::make_unique<OESStandardDerivatives>(this);
2504  }
2505  return m_oesStandardDerivatives.get();
2506  }
2507  if (equalIgnoringCase(name, "OES_texture_float")
2508  && m_context->getExtensions()->supports("GL_OES_texture_float")) {
2509  if (!m_oesTextureFloat) {
2510  m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
2511  m_oesTextureFloat = std::make_unique<OESTextureFloat>(this);
2512  }
2513  return m_oesTextureFloat.get();
2514  }
2515  if (equalIgnoringCase(name, "OES_texture_float_linear")
2516  && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) {
2517  if (!m_oesTextureFloatLinear) {
2518  m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear");
2519  m_oesTextureFloatLinear = std::make_unique<OESTextureFloatLinear>(this);
2520  }
2521  return m_oesTextureFloatLinear.get();
2522  }
2523  if (equalIgnoringCase(name, "OES_texture_half_float")
2524  && m_context->getExtensions()->supports("GL_OES_texture_half_float")) {
2525  if (!m_oesTextureHalfFloat) {
2526  m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float");
2527  m_oesTextureHalfFloat = std::make_unique<OESTextureHalfFloat>(this);
2528  }
2529  return m_oesTextureHalfFloat.get();
2530  }
2531  if (equalIgnoringCase(name, "OES_texture_half_float_linear")
2532  && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) {
2533  if (!m_oesTextureHalfFloatLinear) {
2534  m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear");
2535  m_oesTextureHalfFloatLinear = std::make_unique<OESTextureHalfFloatLinear>(this);
2536  }
2537  return m_oesTextureHalfFloatLinear.get();
2538  }
2539  if (equalIgnoringCase(name, "OES_vertex_array_object")
2540  && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
2541  if (!m_oesVertexArrayObject) {
2542  m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
2543  m_oesVertexArrayObject = std::make_unique<OESVertexArrayObject>(this);
2544  }
2545  return m_oesVertexArrayObject.get();
2546  }
2547  if (equalIgnoringCase(name, "OES_element_index_uint")
2548  && m_context->getExtensions()->supports("GL_OES_element_index_uint")) {
2549  if (!m_oesElementIndexUint) {
2550  m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint");
2551  m_oesElementIndexUint = std::make_unique<OESElementIndexUint>(this);
2552  }
2553  return m_oesElementIndexUint.get();
2554  }
2555  if (equalIgnoringCase(name, "WEBGL_lose_context")) {
2556  if (!m_webglLoseContext)
2557  m_webglLoseContext = std::make_unique<WebGLLoseContext>(this);
2558  return m_webglLoseContext.get();
2559  }
2560  if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_atc"))
2561  && WebGLCompressedTextureATC::supported(this)) {
2562  if (!m_webglCompressedTextureATC)
2563  m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(this);
2564  return m_webglCompressedTextureATC.get();
2565  }
2566  if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc"))
2567  && WebGLCompressedTexturePVRTC::supported(this)) {
2568  if (!m_webglCompressedTexturePVRTC)
2569  m_webglCompressedTexturePVRTC = std::make_unique<WebGLCompressedTexturePVRTC>(this);
2570  return m_webglCompressedTexturePVRTC.get();
2571  }
2572  if (equalIgnoringCase(name, "WEBGL_compressed_texture_s3tc")
2573  && WebGLCompressedTextureS3TC::supported(this)) {
2574  if (!m_webglCompressedTextureS3TC)
2575  m_webglCompressedTextureS3TC = std::make_unique<WebGLCompressedTextureS3TC>(this);
2576  return m_webglCompressedTextureS3TC.get();
2577  }
2578  if (equalIgnoringCase(name, "WEBGL_depth_texture")
2579  && WebGLDepthTexture::supported(graphicsContext3D())) {
2580  if (!m_webglDepthTexture) {
2581  m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
2582  m_webglDepthTexture = std::make_unique<WebGLDepthTexture>(this);
2583  }
2584  return m_webglDepthTexture.get();
2585  }
2586  if (equalIgnoringCase(name, "WEBGL_draw_buffers") && supportsDrawBuffers()) {
2587  if (!m_webglDrawBuffers) {
2588  m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
2589  m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(this);
2590  }
2591  return m_webglDrawBuffers.get();
2592  }
2593  if (equalIgnoringCase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) {
2594  if (!m_angleInstancedArrays) {
2595  m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays");
2596  m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(this);
2597  }
2598  return m_angleInstancedArrays.get();
2599  }
2600  if (allowPrivilegedExtensions()) {
2601  if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) {
2602  if (!m_webglDebugRendererInfo)
2603  m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(this);
2604  return m_webglDebugRendererInfo.get();
2605  }
2606  if (equalIgnoringCase(name, "WEBGL_debug_shaders")
2607  && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
2608  if (!m_webglDebugShaders)
2609  m_webglDebugShaders = std::make_unique<WebGLDebugShaders>(this);
2610  return m_webglDebugShaders.get();
2611  }
2612  }
2613 
2614  return nullptr;
2615 }
2616 
2617 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
2618 {
2619  UNUSED_PARAM(ec);
2620  if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
2621  return WebGLGetInfo();
2622 
2623  if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2624  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
2625  return WebGLGetInfo();
2626  }
2627 
2628  WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
2629  if (!object) {
2630  if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2631  return WebGLGetInfo(GraphicsContext3D::NONE);
2632  // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
2633  // specifies INVALID_OPERATION.
2634  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
2635  return WebGLGetInfo();
2636  }
2637 
2638  ASSERT(object->isTexture() || object->isRenderbuffer());
2639  if (object->isTexture()) {
2640  switch (pname) {
2641  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2642  return WebGLGetInfo(GraphicsContext3D::TEXTURE);
2643  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2644  return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
2645  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2646  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2647  case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
2648  GC3Dint value = 0;
2649  m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
2650  return WebGLGetInfo(value);
2651  }
2652  default:
2653  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
2654  return WebGLGetInfo();
2655  }
2656  } else {
2657  switch (pname) {
2658  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2659  return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
2660  case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2661  return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
2662  case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
2663  WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
2664  GC3Denum renderBufferFormat = renderBuffer->getInternalFormat();
2665  ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT);
2666  if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT)
2667  return WebGLGetInfo(Extensions3D::SRGB_EXT);
2668  return WebGLGetInfo(GraphicsContext3D::LINEAR);
2669  }
2670  default:
2671  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
2672  return WebGLGetInfo();
2673  }
2674  }
2675 }
2676 
2677 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
2678 {
2679  UNUSED_PARAM(ec);
2680  if (isContextLostOrPending())
2681  return WebGLGetInfo();
2682  const int intZero = 0;
2683  switch (pname) {
2684  case GraphicsContext3D::ACTIVE_TEXTURE:
2685  return getUnsignedIntParameter(pname);
2686  case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2687  return getWebGLFloatArrayParameter(pname);
2688  case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2689  return getWebGLFloatArrayParameter(pname);
2690  case GraphicsContext3D::ALPHA_BITS:
2691  return getIntParameter(pname);
2692  case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2693  return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2694  case GraphicsContext3D::BLEND:
2695  return getBooleanParameter(pname);
2696  case GraphicsContext3D::BLEND_COLOR:
2697  return getWebGLFloatArrayParameter(pname);
2698  case GraphicsContext3D::BLEND_DST_ALPHA:
2699  return getUnsignedIntParameter(pname);
2700  case GraphicsContext3D::BLEND_DST_RGB:
2701  return getUnsignedIntParameter(pname);
2702  case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2703  return getUnsignedIntParameter(pname);
2704  case GraphicsContext3D::BLEND_EQUATION_RGB:
2705  return getUnsignedIntParameter(pname);
2706  case GraphicsContext3D::BLEND_SRC_ALPHA:
2707  return getUnsignedIntParameter(pname);
2708  case GraphicsContext3D::BLEND_SRC_RGB:
2709  return getUnsignedIntParameter(pname);
2710  case GraphicsContext3D::BLUE_BITS:
2711  return getIntParameter(pname);
2712  case GraphicsContext3D::COLOR_CLEAR_VALUE:
2713  return getWebGLFloatArrayParameter(pname);
2714  case GraphicsContext3D::COLOR_WRITEMASK:
2715  return getBooleanArrayParameter(pname);
2716  case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2717  return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()));
2718  case GraphicsContext3D::CULL_FACE:
2719  return getBooleanParameter(pname);
2720  case GraphicsContext3D::CULL_FACE_MODE:
2721  return getUnsignedIntParameter(pname);
2722  case GraphicsContext3D::CURRENT_PROGRAM:
2723  return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2724  case GraphicsContext3D::DEPTH_BITS:
2725  if (!m_framebufferBinding && !m_attributes.depth)
2726  return WebGLGetInfo(intZero);
2727  return getIntParameter(pname);
2728  case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2729  return getFloatParameter(pname);
2730  case GraphicsContext3D::DEPTH_FUNC:
2731  return getUnsignedIntParameter(pname);
2732  case GraphicsContext3D::DEPTH_RANGE:
2733  return getWebGLFloatArrayParameter(pname);
2734  case GraphicsContext3D::DEPTH_TEST:
2735  return getBooleanParameter(pname);
2736  case GraphicsContext3D::DEPTH_WRITEMASK:
2737  return getBooleanParameter(pname);
2738  case GraphicsContext3D::DITHER:
2739  return getBooleanParameter(pname);
2740  case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2741  return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
2742  case GraphicsContext3D::FRAMEBUFFER_BINDING:
2743  return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2744  case GraphicsContext3D::FRONT_FACE:
2745  return getUnsignedIntParameter(pname);
2746  case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2747  return getUnsignedIntParameter(pname);
2748  case GraphicsContext3D::GREEN_BITS:
2749  return getIntParameter(pname);
2750  case GraphicsContext3D::LINE_WIDTH:
2751  return getFloatParameter(pname);
2752  case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2753  return getIntParameter(pname);
2754  case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2755  return getIntParameter(pname);
2756  case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2757  return getIntParameter(pname);
2758  case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2759  return getIntParameter(pname);
2760  case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2761  return getIntParameter(pname);
2762  case GraphicsContext3D::MAX_TEXTURE_SIZE:
2763  return getIntParameter(pname);
2764  case GraphicsContext3D::MAX_VARYING_VECTORS:
2765  return getIntParameter(pname);
2766  case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2767  return getIntParameter(pname);
2768  case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2769  return getIntParameter(pname);
2770  case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2771  return getIntParameter(pname);
2772  case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2773  return getWebGLIntArrayParameter(pname);
2774  case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2775  // FIXME: should we always return 0 for this?
2776  return getIntParameter(pname);
2777  case GraphicsContext3D::PACK_ALIGNMENT:
2778  return getIntParameter(pname);
2779  case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2780  return getFloatParameter(pname);
2781  case GraphicsContext3D::POLYGON_OFFSET_FILL:
2782  return getBooleanParameter(pname);
2783  case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2784  return getFloatParameter(pname);
2785  case GraphicsContext3D::RED_BITS:
2786  return getIntParameter(pname);
2787  case GraphicsContext3D::RENDERBUFFER_BINDING:
2788  return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
2789  case GraphicsContext3D::RENDERER:
2790  return WebGLGetInfo(String("WebKit WebGL"));
2791  case GraphicsContext3D::SAMPLE_BUFFERS:
2792  return getIntParameter(pname);
2793  case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2794  return getBooleanParameter(pname);
2795  case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2796  return getFloatParameter(pname);
2797  case GraphicsContext3D::SAMPLES:
2798  return getIntParameter(pname);
2799  case GraphicsContext3D::SCISSOR_BOX:
2800  return getWebGLIntArrayParameter(pname);
2801  case GraphicsContext3D::SCISSOR_TEST:
2802  return getBooleanParameter(pname);
2803  case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2804  return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
2805  case GraphicsContext3D::STENCIL_BACK_FAIL:
2806  return getUnsignedIntParameter(pname);
2807  case GraphicsContext3D::STENCIL_BACK_FUNC:
2808  return getUnsignedIntParameter(pname);
2809  case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2810  return getUnsignedIntParameter(pname);
2811  case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2812  return getUnsignedIntParameter(pname);
2813  case GraphicsContext3D::STENCIL_BACK_REF:
2814  return getIntParameter(pname);
2815  case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2816  return getUnsignedIntParameter(pname);
2817  case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2818  return getUnsignedIntParameter(pname);
2819  case GraphicsContext3D::STENCIL_BITS:
2820  if (!m_framebufferBinding && !m_attributes.stencil)
2821  return WebGLGetInfo(intZero);
2822  return getIntParameter(pname);
2823  case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2824  return getIntParameter(pname);
2825  case GraphicsContext3D::STENCIL_FAIL:
2826  return getUnsignedIntParameter(pname);
2827  case GraphicsContext3D::STENCIL_FUNC:
2828  return getUnsignedIntParameter(pname);
2829  case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2830  return getUnsignedIntParameter(pname);
2831  case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2832  return getUnsignedIntParameter(pname);
2833  case GraphicsContext3D::STENCIL_REF:
2834  return getIntParameter(pname);
2835  case GraphicsContext3D::STENCIL_TEST:
2836  return getBooleanParameter(pname);
2837  case GraphicsContext3D::STENCIL_VALUE_MASK:
2838  return getUnsignedIntParameter(pname);
2839  case GraphicsContext3D::STENCIL_WRITEMASK:
2840  return getUnsignedIntParameter(pname);
2841  case GraphicsContext3D::SUBPIXEL_BITS:
2842  return getIntParameter(pname);
2843  case GraphicsContext3D::TEXTURE_BINDING_2D:
2844  return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding));
2845  case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2846  return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding));
2847  case GraphicsContext3D::UNPACK_ALIGNMENT:
2848  return getIntParameter(pname);
2849  case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2850  return WebGLGetInfo(m_unpackFlipY);
2851  case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2852  return WebGLGetInfo(m_unpackPremultiplyAlpha);
2853  case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2854  return WebGLGetInfo(m_unpackColorspaceConversion);
2855  case GraphicsContext3D::VENDOR:
2856  return WebGLGetInfo(String("WebKit"));
2857  case GraphicsContext3D::VERSION:
2858  return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
2859  case GraphicsContext3D::VIEWPORT:
2860  return getWebGLIntArrayParameter(pname);
2861  case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2862  if (m_oesStandardDerivatives)
2863  return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2864  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
2865  return WebGLGetInfo();
2866  case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
2867  if (m_webglDebugRendererInfo)
2868  return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
2869  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2870  return WebGLGetInfo();
2871  case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
2872  if (m_webglDebugRendererInfo)
2873  return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
2874  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2875  return WebGLGetInfo();
2876  case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2877  if (m_oesVertexArrayObject) {
2878  if (!m_boundVertexArrayObject->isDefaultObject())
2879  return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
2880  return WebGLGetInfo();
2881  }
2882  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
2883  return WebGLGetInfo();
2884  case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
2885  if (m_extTextureFilterAnisotropic)
2886  return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
2887  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
2888  return WebGLGetInfo();
2889  case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
2890  if (m_webglDrawBuffers)
2891  return WebGLGetInfo(getMaxColorAttachments());
2892  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
2893  return WebGLGetInfo();
2894  case Extensions3D::MAX_DRAW_BUFFERS_EXT:
2895  if (m_webglDrawBuffers)
2896  return WebGLGetInfo(getMaxDrawBuffers());
2897  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
2898  return WebGLGetInfo();
2899  default:
2900  if (m_webglDrawBuffers
2901  && pname >= Extensions3D::DRAW_BUFFER0_EXT
2902  && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
2903  GC3Dint value = GraphicsContext3D::NONE;
2904  if (m_framebufferBinding)
2905  value = m_framebufferBinding->getDrawBuffer(pname);
2906  else // emulated backbuffer
2907  value = m_backDrawBuffer;
2908  return WebGLGetInfo(value);
2909  }
2910  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
2911  return WebGLGetInfo();
2912  }
2913 }
2914 
2915 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
2916 {
2917  UNUSED_PARAM(ec);
2918  if (isContextLostOrPending() || !validateWebGLObject("getProgramParameter", program))
2919  return WebGLGetInfo();
2920 
2921  GC3Dint value = 0;
2922  switch (pname) {
2923  case GraphicsContext3D::DELETE_STATUS:
2924  return WebGLGetInfo(program->isDeleted());
2925  case GraphicsContext3D::VALIDATE_STATUS:
2926  m_context->getProgramiv(objectOrZero(program), pname, &value);
2927  return WebGLGetInfo(static_cast<bool>(value));
2928  case GraphicsContext3D::LINK_STATUS:
2929  return WebGLGetInfo(program->getLinkStatus());
2930  case GraphicsContext3D::ATTACHED_SHADERS:
2931  m_context->getProgramiv(objectOrZero(program), pname, &value);
2932  return WebGLGetInfo(value);
2933  case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2934  case GraphicsContext3D::ACTIVE_UNIFORMS:
2935  m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), pname, &value);
2936  return WebGLGetInfo(value);
2937  default:
2938  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name");
2939  return WebGLGetInfo();
2940  }
2941 }
2942 
2943 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
2944 {
2945  UNUSED_PARAM(ec);
2946  if (isContextLostOrPending())
2947  return String();
2948  if (!validateWebGLObject("getProgramInfoLog", program))
2949  return "";
2950  return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
2951 }
2952 
2953 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2954 {
2955  UNUSED_PARAM(ec);
2956  if (isContextLostOrPending())
2957  return WebGLGetInfo();
2958  if (target != GraphicsContext3D::RENDERBUFFER) {
2959  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target");
2960  return WebGLGetInfo();
2961  }
2962  if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2963  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound");
2964  return WebGLGetInfo();
2965  }
2966 
2967  if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
2968  && !m_renderbufferBinding->isValid()) {
2969  ASSERT(!isDepthStencilSupported());
2970  int value = 0;
2971  switch (pname) {
2972  case GraphicsContext3D::RENDERBUFFER_WIDTH:
2973  value = m_renderbufferBinding->getWidth();
2974  break;
2975  case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2976  value = m_renderbufferBinding->getHeight();
2977  break;
2978  case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2979  case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2980  case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2981  case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2982  value = 0;
2983  break;
2984  case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2985  value = 24;
2986  break;
2987  case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2988  value = 8;
2989  break;
2990  case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2991  return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2992  default:
2993  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2994  return WebGLGetInfo();
2995  }
2996  return WebGLGetInfo(value);
2997  }
2998 
2999  GC3Dint value = 0;
3000  switch (pname) {
3001  case GraphicsContext3D::RENDERBUFFER_WIDTH:
3002  case GraphicsContext3D::RENDERBUFFER_HEIGHT:
3003  case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
3004  case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
3005  case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
3006  case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
3007  case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
3008  case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
3009  m_context->getRenderbufferParameteriv(target, pname, &value);
3010  return WebGLGetInfo(value);
3011  case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
3012  return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
3013  default:
3014  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
3015  return WebGLGetInfo();
3016  }
3017 }
3018 
3019 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
3020 {
3021  UNUSED_PARAM(ec);
3022  if (isContextLostOrPending() || !validateWebGLObject("getShaderParameter", shader))
3023  return WebGLGetInfo();
3024  GC3Dint value = 0;
3025  switch (pname) {
3026  case GraphicsContext3D::DELETE_STATUS:
3027  return WebGLGetInfo(shader->isDeleted());
3028  case GraphicsContext3D::COMPILE_STATUS:
3029  m_context->getShaderiv(objectOrZero(shader), pname, &value);
3030  return WebGLGetInfo(static_cast<bool>(value));
3031  case GraphicsContext3D::SHADER_TYPE:
3032  m_context->getShaderiv(objectOrZero(shader), pname, &value);
3033  return WebGLGetInfo(static_cast<unsigned int>(value));
3034  default:
3035  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
3036  return WebGLGetInfo();
3037  }
3038 }
3039 
3040 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
3041 {
3042  UNUSED_PARAM(ec);
3043  if (isContextLostOrPending())
3044  return String();
3045  if (!validateWebGLObject("getShaderInfoLog", shader))
3046  return "";
3047  return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
3048 }
3049 
3050 PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec)
3051 {
3052  UNUSED_PARAM(ec);
3053  if (isContextLostOrPending())
3054  return nullptr;
3055  switch (shaderType) {
3056  case GraphicsContext3D::VERTEX_SHADER:
3057  case GraphicsContext3D::FRAGMENT_SHADER:
3058  break;
3059  default:
3060  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type");
3061  return nullptr;
3062  }
3063  switch (precisionType) {
3064  case GraphicsContext3D::LOW_FLOAT:
3065  case GraphicsContext3D::MEDIUM_FLOAT:
3066  case GraphicsContext3D::HIGH_FLOAT:
3067  case GraphicsContext3D::LOW_INT:
3068  case GraphicsContext3D::MEDIUM_INT:
3069  case GraphicsContext3D::HIGH_INT:
3070  break;
3071  default:
3072  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type");
3073  return nullptr;
3074  }
3075 
3076  GC3Dint range[2] = {0, 0};
3077  GC3Dint precision = 0;
3078  m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision);
3079  return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
3080 }
3081 
3082 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
3083 {
3084  UNUSED_PARAM(ec);
3085  if (isContextLostOrPending())
3086  return String();
3087  if (!validateWebGLObject("getShaderSource", shader))
3088  return "";
3089  return ensureNotNull(shader->getSource());
3090 }
3091 
3092 Vector<String> WebGLRenderingContext::getSupportedExtensions()
3093 {
3094  Vector<String> result;
3095 
3096  if (m_isPendingPolicyResolution)
3097  return result;
3098 
3099  if (m_context->getExtensions()->supports("GL_EXT_blend_minmax"))
3100  result.append("EXT_blend_minmax");
3101  if (m_context->getExtensions()->supports("GL_EXT_sRGB"))
3102  result.append("EXT_sRGB");
3103  if (m_context->getExtensions()->supports("GL_EXT_frag_depth"))
3104  result.append("EXT_frag_depth");
3105  if (m_context->getExtensions()->supports("GL_OES_texture_float"))
3106  result.append("OES_texture_float");
3107  if (m_context->getExtensions()->supports("GL_OES_texture_float_linear"))
3108  result.append("OES_texture_float_linear");
3109  if (m_context->getExtensions()->supports("GL_OES_texture_half_float"))
3110  result.append("OES_texture_half_float");
3111  if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear"))
3112  result.append("OES_texture_half_float_linear");
3113  if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
3114  result.append("OES_standard_derivatives");
3115  if (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))
3116  result.append("EXT_shader_texture_lod");
3117  if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
3118  result.append("WEBKIT_EXT_texture_filter_anisotropic");
3119  if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
3120  result.append("OES_vertex_array_object");
3121  if (m_context->getExtensions()->supports("GL_OES_element_index_uint"))
3122  result.append("OES_element_index_uint");
3123  result.append("WEBGL_lose_context");
3124  if (WebGLCompressedTextureATC::supported(this))
3125  result.append("WEBKIT_WEBGL_compressed_texture_atc");
3126  if (WebGLCompressedTexturePVRTC::supported(this))
3127  result.append("WEBKIT_WEBGL_compressed_texture_pvrtc");
3128  if (WebGLCompressedTextureS3TC::supported(this))
3129  result.append("WEBGL_compressed_texture_s3tc");
3130  if (WebGLDepthTexture::supported(graphicsContext3D()))
3131  result.append("WEBGL_depth_texture");
3132  if (supportsDrawBuffers())
3133  result.append("WEBGL_draw_buffers");
3134  if (ANGLEInstancedArrays::supported(this))
3135  result.append("ANGLE_instanced_arrays");
3136 
3137  if (allowPrivilegedExtensions()) {
3138  if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
3139  result.append("WEBGL_debug_shaders");
3140  result.append("WEBGL_debug_renderer_info");
3141  }
3142 
3143  return result;
3144 }
3145 
3146 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
3147 {
3148  UNUSED_PARAM(ec);
3149  if (isContextLostOrPending())
3150  return WebGLGetInfo();
3151  WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false);
3152  if (!tex)
3153  return WebGLGetInfo();
3154  GC3Dint value = 0;
3155  switch (pname) {
3156  case GraphicsContext3D::TEXTURE_MAG_FILTER:
3157  case GraphicsContext3D::TEXTURE_MIN_FILTER:
3158  case GraphicsContext3D::TEXTURE_WRAP_S:
3159  case GraphicsContext3D::TEXTURE_WRAP_T:
3160  m_context->getTexParameteriv(target, pname, &value);
3161  return WebGLGetInfo(static_cast<unsigned int>(value));
3162  case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
3163  if (m_extTextureFilterAnisotropic) {
3164  m_context->getTexParameteriv(target, pname, &value);
3165  return WebGLGetInfo(static_cast<unsigned int>(value));
3166  }
3167  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
3168  return WebGLGetInfo();
3169  default:
3170  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name");
3171  return WebGLGetInfo();
3172  }
3173 }
3174 
3175 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
3176 {
3177  UNUSED_PARAM(ec);
3178  if (isContextLostOrPending() || !validateWebGLObject("getUniform", program))
3179  return WebGLGetInfo();
3180  if (!uniformLocation || uniformLocation->program() != program) {
3181  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program");
3182  return WebGLGetInfo();
3183  }
3184  GC3Dint location = uniformLocation->location();
3185 
3186  GC3Denum baseType;
3187  unsigned length;
3188  switch (uniformLocation->type()) {
3189  case GraphicsContext3D::BOOL:
3190  baseType = GraphicsContext3D::BOOL;
3191  length = 1;
3192  break;
3193  case GraphicsContext3D::BOOL_VEC2:
3194  baseType = GraphicsContext3D::BOOL;
3195  length = 2;
3196  break;
3197  case GraphicsContext3D::BOOL_VEC3:
3198  baseType = GraphicsContext3D::BOOL;
3199  length = 3;
3200  break;
3201  case GraphicsContext3D::BOOL_VEC4:
3202  baseType = GraphicsContext3D::BOOL;
3203  length = 4;
3204  break;
3205  case GraphicsContext3D::INT:
3206  baseType = GraphicsContext3D::INT;
3207  length = 1;
3208  break;
3209  case GraphicsContext3D::INT_VEC2:
3210  baseType = GraphicsContext3D::INT;
3211  length = 2;
3212  break;
3213  case GraphicsContext3D::INT_VEC3:
3214  baseType = GraphicsContext3D::INT;
3215  length = 3;
3216  break;
3217  case GraphicsContext3D::INT_VEC4:
3218  baseType = GraphicsContext3D::INT;
3219  length = 4;
3220  break;
3221  case GraphicsContext3D::FLOAT:
3222  baseType = GraphicsContext3D::FLOAT;
3223  length = 1;
3224  break;
3225  case GraphicsContext3D::FLOAT_VEC2:
3226  baseType = GraphicsContext3D::FLOAT;
3227  length = 2;
3228  break;
3229  case GraphicsContext3D::FLOAT_VEC3:
3230  baseType = GraphicsContext3D::FLOAT;
3231  length = 3;
3232  break;
3233  case GraphicsContext3D::FLOAT_VEC4:
3234  baseType = GraphicsContext3D::FLOAT;
3235  length = 4;
3236  break;
3237  case GraphicsContext3D::FLOAT_MAT2:
3238  baseType = GraphicsContext3D::FLOAT;
3239  length = 4;
3240  break;
3241  case GraphicsContext3D::FLOAT_MAT3:
3242  baseType = GraphicsContext3D::FLOAT;
3243  length = 9;
3244  break;
3245  case GraphicsContext3D::FLOAT_MAT4:
3246  baseType = GraphicsContext3D::FLOAT;
3247  length = 16;
3248  break;
3249  case GraphicsContext3D::SAMPLER_2D:
3250  case GraphicsContext3D::SAMPLER_CUBE:
3251  baseType = GraphicsContext3D::INT;
3252  length = 1;
3253  break;
3254  default:
3255  // Can't handle this type
3256  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type");
3257  return WebGLGetInfo();
3258  }
3259  switch (baseType) {
3260  case GraphicsContext3D::FLOAT: {
3261  GC3Dfloat value[16] = {0};
3262  if (m_isRobustnessEXTSupported)
3263  m_context->getExtensions()->getnUniformfvEXT(objectOrZero(program), location, 16 * sizeof(GC3Dfloat), value);
3264  else
3265  m_context->getUniformfv(objectOrZero(program), location, value);
3266  if (length == 1)
3267  return WebGLGetInfo(value[0]);
3268  return WebGLGetInfo(Float32Array::create(value, length));
3269  }
3270  case GraphicsContext3D::INT: {
3271  GC3Dint value[4] = {0};
3272  if (m_isRobustnessEXTSupported)
3273  m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
3274  else
3275  m_context->getUniformiv(objectOrZero(program), location, value);
3276  if (length == 1)
3277  return WebGLGetInfo(value[0]);
3278  return WebGLGetInfo(Int32Array::create(value, length));
3279  }
3280  case GraphicsContext3D::BOOL: {
3281  GC3Dint value[4] = {0};
3282  if (m_isRobustnessEXTSupported)
3283  m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
3284  else
3285  m_context->getUniformiv(objectOrZero(program), location, value);
3286  if (length > 1) {
3287  bool boolValue[16] = {0};
3288  for (unsigned j = 0; j < length; j++)
3289  boolValue[j] = static_cast<bool>(value[j]);
3290  return WebGLGetInfo(boolValue, length);
3291  }
3292  return WebGLGetInfo(static_cast<bool>(value[0]));
3293  }
3294  default:
3295  notImplemented();
3296  }
3297 
3298  // If we get here, something went wrong in our unfortunately complex logic above
3299  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error");
3300  return WebGLGetInfo();
3301 }
3302 
3303 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
3304 {
3305  UNUSED_PARAM(ec);
3306  if (isContextLostOrPending() || !validateWebGLObject("getUniformLocation", program))
3307  return nullptr;
3308  if (!validateLocationLength("getUniformLocation", name))
3309  return nullptr;
3310  if (!validateString("getUniformLocation", name))
3311  return nullptr;
3312  if (isPrefixReserved(name))
3313  return nullptr;
3314  if (!program->getLinkStatus()) {
3315  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked");
3316  return nullptr;
3317  }
3318  GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
3319  if (uniformLocation == -1)
3320  return nullptr;
3321 
3322  GC3Dint activeUniforms = 0;
3323  m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
3324  for (GC3Dint i = 0; i < activeUniforms; i++) {
3325  ActiveInfo info;
3326  if (!m_context->getActiveUniform(objectOrZero(program), i, info))
3327  return nullptr;
3328  // Strip "[0]" from the name if it's an array.
3329  if (info.name.endsWith("[0]"))
3330  info.name = info.name.left(info.name.length() - 3);
3331  // If it's an array, we need to iterate through each element, appending "[index]" to the name.
3332  for (GC3Dint index = 0; index < info.size; ++index) {
3333  String uniformName = info.name + "[" + String::number(index) + "]";
3334 
3335  if (name == uniformName || name == info.name)
3336  return WebGLUniformLocation::create(program, uniformLocation, info.type);
3337  }
3338  }
3339  return nullptr;
3340 }
3341 
3342 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
3343 {
3344  UNUSED_PARAM(ec);
3345 
3346  if (isContextLostOrPending())
3347  return WebGLGetInfo();
3348 
3349  if (index >= m_maxVertexAttribs) {
3350  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range");
3351  return WebGLGetInfo();
3352  }
3353 
3354  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
3355 
3356  if (m_angleInstancedArrays && pname == GraphicsContext3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE)
3357  return WebGLGetInfo(state.divisor);
3358 
3359  switch (pname) {
3360  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3361  if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
3362  || !state.bufferBinding
3363  || !state.bufferBinding->object())
3364  return WebGLGetInfo();
3365  return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
3366  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
3367  return WebGLGetInfo(state.enabled);
3368  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
3369  return WebGLGetInfo(state.normalized);
3370  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
3371  return WebGLGetInfo(state.size);
3372  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
3373  return WebGLGetInfo(state.originalStride);
3374  case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
3375  return WebGLGetInfo(state.type);
3376  case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
3377  return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
3378  default:
3379  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name");
3380  return WebGLGetInfo();
3381  }
3382 }
3383 
3384 long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
3385 {
3386  if (isContextLostOrPending())
3387  return 0;
3388  GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
3389  return static_cast<long long>(result);
3390 }
3391 
3392 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
3393 {
3394  if (isContextLostOrPending())
3395  return;
3396  bool isValid = false;
3397  switch (target) {
3398  case GraphicsContext3D::GENERATE_MIPMAP_HINT:
3399  isValid = true;
3400  break;
3401  case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
3402  if (m_oesStandardDerivatives)
3403  isValid = true;
3404  break;
3405  }
3406  if (!isValid) {
3407  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
3408  return;
3409  }
3410  m_context->hint(target, mode);
3411 }
3412 
3413 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
3414 {
3415  if (!buffer || isContextLostOrPending())
3416  return 0;
3417 
3418  if (!buffer->hasEverBeenBound())
3419  return 0;
3420 
3421  return m_context->isBuffer(buffer->object());
3422 }
3423 
3424 bool WebGLRenderingContext::isContextLost() const
3425 {
3426  return m_contextLost;
3427 }
3428 
3429 bool WebGLRenderingContext::isContextLostOrPending()
3430 {
3431  if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) {
3432  LOG(WebGL, "Context is being used. Attempt to resolve the policy.");
3433  Document& document = canvas()->document().topDocument();
3434  Page* page = document.page();
3435  if (page && !document.url().isLocalFile())
3436  page->mainFrame().loader().client().resolveWebGLPolicyForURL(document.url());
3437  // FIXME: We don't currently do anything with the result from resolution. A more
3438  // complete implementation might try to construct a real context, etc and proceed
3439  // with normal operation.
3440  // https://bugs.webkit.org/show_bug.cgi?id=129122
3441  m_hasRequestedPolicyResolution = true;
3442  }
3443 
3444  return m_contextLost || m_isPendingPolicyResolution;
3445 }
3446 
3447 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
3448 {
3449  if (isContextLostOrPending() || !validateCapability("isEnabled", cap))
3450  return 0;
3451  if (cap == GraphicsContext3D::STENCIL_TEST)
3452  return m_stencilEnabled;
3453  return m_context->isEnabled(cap);
3454 }
3455 
3456 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
3457 {
3458  if (!framebuffer || isContextLostOrPending())
3459  return 0;
3460 
3461  if (!framebuffer->hasEverBeenBound())
3462  return 0;
3463 
3464  return m_context->isFramebuffer(framebuffer->object());
3465 }
3466 
3467 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
3468 {
3469  if (!program || isContextLostOrPending())
3470  return 0;
3471 
3472  return m_context->isProgram(program->object());
3473 }
3474 
3475 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
3476 {
3477  if (!renderbuffer || isContextLostOrPending())
3478  return 0;
3479 
3480  if (!renderbuffer->hasEverBeenBound())
3481  return 0;
3482 
3483  return m_context->isRenderbuffer(renderbuffer->object());
3484 }
3485 
3486 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
3487 {
3488  if (!shader || isContextLostOrPending())
3489  return 0;
3490 
3491  return m_context->isShader(shader->object());
3492 }
3493 
3494 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
3495 {
3496  if (!texture || isContextLostOrPending())
3497  return 0;
3498 
3499  if (!texture->hasEverBeenBound())
3500  return 0;
3501 
3502  return m_context->isTexture(texture->object());
3503 }
3504 
3505 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
3506 {
3507  if (isContextLostOrPending())
3508  return;
3509  m_context->lineWidth(width);
3510 }
3511 
3512 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
3513 {
3514  UNUSED_PARAM(ec);
3515  if (isContextLostOrPending() || !validateWebGLObject("linkProgram", program))
3516  return;
3517  if (!isGLES2Compliant()) {
3518  WebGLShader* vertexShader = program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER);
3519  WebGLShader* fragmentShader = program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER);
3520  if (!vertexShader || !vertexShader->isValid() || !fragmentShader || !fragmentShader->isValid() || !m_context->precisionsMatch(objectOrZero(vertexShader), objectOrZero(fragmentShader)) || !m_context->checkVaryingsPacking(objectOrZero(vertexShader), objectOrZero(fragmentShader))) {
3521  program->setLinkStatus(false);
3522  return;
3523  }
3524  }
3525 
3526  m_context->linkProgram(objectOrZero(program));
3527  program->increaseLinkCount();
3528 }
3529 
3530 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
3531 {
3532  if (isContextLostOrPending())
3533  return;
3534  switch (pname) {
3535  case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
3536  m_unpackFlipY = param;
3537  break;
3538  case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
3539  m_unpackPremultiplyAlpha = param;
3540  break;
3541  case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
3542  if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
3543  m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
3544  else {
3545  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
3546  return;
3547  }
3548  break;
3549  case GraphicsContext3D::PACK_ALIGNMENT:
3550  case GraphicsContext3D::UNPACK_ALIGNMENT:
3551  if (param == 1 || param == 2 || param == 4 || param == 8) {
3552  if (pname == GraphicsContext3D::PACK_ALIGNMENT)
3553  m_packAlignment = param;
3554  else // GraphicsContext3D::UNPACK_ALIGNMENT:
3555  m_unpackAlignment = param;
3556  m_context->pixelStorei(pname, param);
3557  } else {
3558  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment");
3559  return;
3560  }
3561  break;
3562  default:
3563  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name");
3564  return;
3565  }
3566 }
3567 
3568 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
3569 {
3570  if (isContextLostOrPending())
3571  return;
3572  m_context->polygonOffset(factor, units);
3573 }
3574 
3575 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
3576 {
3577  if (isContextLostOrPending())
3578  return;
3579  // Due to WebGL's same-origin restrictions, it is not possible to
3580  // taint the origin using the WebGL API.
3581  ASSERT(canvas()->originClean());
3582  // Validate input parameters.
3583  if (!pixels) {
3584  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView");
3585  return;
3586  }
3587  switch (format) {
3588  case GraphicsContext3D::ALPHA:
3589  case GraphicsContext3D::RGB:
3590  case GraphicsContext3D::RGBA:
3591  break;
3592  default:
3593  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
3594  return;
3595  }
3596  switch (type) {
3597  case GraphicsContext3D::UNSIGNED_BYTE:
3598  case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3599  case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3600  case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3601  break;
3602  default:
3603  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
3604  return;
3605  }
3606  if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
3607  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
3608  return;
3609  }
3610  // Validate array type against pixel type.
3611  if (pixels->getType() != JSC::TypeUint8) {
3612  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
3613  return;
3614  }
3615  const char* reason = "framebuffer incomplete";
3616  if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
3617  synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
3618  return;
3619  }
3620  // Calculate array size, taking into consideration of PACK_ALIGNMENT.
3621  unsigned int totalBytesRequired = 0;
3622  unsigned int padding = 0;
3623  if (!m_isRobustnessEXTSupported) {
3624  GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
3625  if (error != GraphicsContext3D::NO_ERROR) {
3626  synthesizeGLError(error, "readPixels", "invalid dimensions");
3627  return;
3628  }
3629  if (pixels->byteLength() < totalBytesRequired) {
3630  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
3631  return;
3632  }
3633  }
3634 
3635  clearIfComposited();
3636  void* data = pixels->baseAddress();
3637 
3638  {
3639  ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
3640  if (m_isRobustnessEXTSupported)
3641  m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels->byteLength(), data);
3642  else
3643  m_context->readPixels(x, y, width, height, format, type, data);
3644  }
3645 
3646 #if OS(DARWIN)
3647  if (m_isRobustnessEXTSupported) // we haven't computed padding
3648  m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
3649  // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
3650  // on QC is fixed, i.e., when alpha is off, readPixels should
3651  // set alpha to 255 instead of 0.
3652  if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
3653  unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
3654  for (GC3Dsizei iy = 0; iy < height; ++iy) {
3655  for (GC3Dsizei ix = 0; ix < width; ++ix) {
3656  pixels[3] = 255;
3657  pixels += 4;
3658  }
3659  pixels += padding;
3660  }
3661  }
3662 #endif
3663 }
3664 
3665 void WebGLRenderingContext::releaseShaderCompiler()
3666 {
3667  if (isContextLostOrPending())
3668  return;
3669  m_context->releaseShaderCompiler();
3670 }
3671 
3672 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
3673 {
3674  if (isContextLostOrPending())
3675  return;
3676  if (target != GraphicsContext3D::RENDERBUFFER) {
3677  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
3678  return;
3679  }
3680  if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
3681  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
3682  return;
3683  }
3684  if (!validateSize("renderbufferStorage", width, height))
3685  return;
3686  switch (internalformat) {
3687  case GraphicsContext3D::DEPTH_COMPONENT16:
3688  case GraphicsContext3D::RGBA4:
3689  case GraphicsContext3D::RGB5_A1:
3690  case GraphicsContext3D::RGB565:
3691  case GraphicsContext3D::STENCIL_INDEX8:
3692  case Extensions3D::SRGB8_ALPHA8_EXT:
3693  if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) {
3694  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
3695  return;
3696  }
3697  m_context->renderbufferStorage(target, internalformat, width, height);
3698  m_renderbufferBinding->setInternalFormat(internalformat);
3699  m_renderbufferBinding->setIsValid(true);
3700  m_renderbufferBinding->setSize(width, height);
3701  break;
3702  case GraphicsContext3D::DEPTH_STENCIL:
3703  if (isDepthStencilSupported()) {
3704  m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
3705  }
3706  m_renderbufferBinding->setSize(width, height);
3707  m_renderbufferBinding->setIsValid(isDepthStencilSupported());
3708  m_renderbufferBinding->setInternalFormat(internalformat);
3709  break;
3710  default:
3711  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
3712  return;
3713  }
3714  applyStencilTest();
3715 }
3716 
3717 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
3718 {
3719  if (isContextLostOrPending())
3720  return;
3721  m_context->sampleCoverage(value, invert);
3722 }
3723 
3724 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
3725 {
3726  if (isContextLostOrPending())
3727  return;
3728  if (!validateSize("scissor", width, height))
3729  return;
3730  m_context->scissor(x, y, width, height);
3731 }
3732 
3733 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
3734 {
3735  UNUSED_PARAM(ec);
3736  if (isContextLostOrPending() || !validateWebGLObject("shaderSource", shader))
3737  return;
3738  String stringWithoutComments = StripComments(string).result();
3739  if (!validateString("shaderSource", stringWithoutComments))
3740  return;
3741  shader->setSource(string);
3742  m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
3743 }
3744 
3745 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
3746 {
3747  if (isContextLostOrPending())
3748  return;
3749  if (!validateStencilFunc("stencilFunc", func))
3750  return;
3751  m_stencilFuncRef = ref;
3752  m_stencilFuncRefBack = ref;
3753  m_stencilFuncMask = mask;
3754  m_stencilFuncMaskBack = mask;
3755  m_context->stencilFunc(func, ref, mask);
3756 }
3757 
3758 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
3759 {
3760  if (isContextLostOrPending())
3761  return;
3762  if (!validateStencilFunc("stencilFuncSeparate", func))
3763  return;
3764  switch (face) {
3765  case GraphicsContext3D::FRONT_AND_BACK:
3766  m_stencilFuncRef = ref;
3767  m_stencilFuncRefBack = ref;
3768  m_stencilFuncMask = mask;
3769  m_stencilFuncMaskBack = mask;
3770  break;
3771  case GraphicsContext3D::FRONT:
3772  m_stencilFuncRef = ref;
3773  m_stencilFuncMask = mask;
3774  break;
3775  case GraphicsContext3D::BACK:
3776  m_stencilFuncRefBack = ref;
3777  m_stencilFuncMaskBack = mask;
3778  break;
3779  default:
3780  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face");
3781  return;
3782  }
3783  m_context->stencilFuncSeparate(face, func, ref, mask);
3784 }
3785 
3786 void WebGLRenderingContext::stencilMask(GC3Duint mask)
3787 {
3788  if (isContextLostOrPending())
3789  return;
3790  m_stencilMask = mask;
3791  m_stencilMaskBack = mask;
3792  m_context->stencilMask(mask);
3793 }
3794 
3795 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3796 {
3797  if (isContextLostOrPending())
3798  return;
3799  switch (face) {
3800  case GraphicsContext3D::FRONT_AND_BACK:
3801  m_stencilMask = mask;
3802  m_stencilMaskBack = mask;
3803  break;
3804  case GraphicsContext3D::FRONT:
3805  m_stencilMask = mask;
3806  break;
3807  case GraphicsContext3D::BACK:
3808  m_stencilMaskBack = mask;
3809  break;
3810  default:
3811  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face");
3812  return;
3813  }
3814  m_context->stencilMaskSeparate(face, mask);
3815 }
3816 
3817 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3818 {
3819  if (isContextLostOrPending())
3820  return;
3821  m_context->stencilOp(fail, zfail, zpass);
3822 }
3823 
3824 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3825 {
3826  if (isContextLostOrPending())
3827  return;
3828  m_context->stencilOpSeparate(face, fail, zfail, zpass);
3829 }
3830 
3831 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
3832 {
3833  // FIXME: For now we ignore any errors returned.
3834  ec = 0;
3835  WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
3836  ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type));
3837  ASSERT(tex);
3838  ASSERT(!level || !WebGLTexture::isNPOT(width, height));
3839  if (!pixels) {
3840  // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true.
3841  // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures
3842  // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
3843  // clear.
3844  if (isResourceSafe())
3845  m_context->texImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
3846  else {
3847  bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
3848  border, format, type, m_unpackAlignment);
3849  if (!succeed)
3850  return;
3851  }
3852  } else {
3853  ASSERT(validateSettableTexFormat("texImage2D", internalformat));
3854  m_context->moveErrorsToSyntheticErrorList();
3855  m_context->texImage2D(target, level, internalformat, width, height,
3856  border, format, type, pixels);
3857  if (m_context->moveErrorsToSyntheticErrorList()) {
3858  // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
3859  tex->markInvalid(target, level);
3860  return;
3861  }
3862  }
3863  tex->setLevelInfo(target, level, internalformat, width, height, type);
3864 }
3865 
3866 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3867 {
3868  ec = 0;
3869  Vector<uint8_t> data;
3870  GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
3871  if (!imageExtractor.extractSucceeded()) {
3872  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3873  return;
3874  }
3875  GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
3876  GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
3877  const void* imagePixelData = imageExtractor.imagePixelData();
3878 
3879  bool needConversion = true;
3880  if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
3881  needConversion = false;
3882  else {
3883  if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
3884  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error");
3885  return;
3886  }
3887  }
3888 
3889  if (m_unpackAlignment != 1)
3890  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3891  texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, ec);
3892  if (m_unpackAlignment != 1)
3893  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3894 }
3895 
3896 bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset)
3897 {
3898  if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type))
3899  return false;
3900 
3901  WebGLTexture* texture = validateTextureBinding(functionName, target, true);
3902  if (!texture)
3903  return false;
3904 
3905  if (functionType == NotTexSubImage2D) {
3906  if (level && WebGLTexture::isNPOT(width, height)) {
3907  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2");
3908  return false;
3909  }
3910  // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
3911  // by checking if the ArrayBufferView is null or not.
3912  if (sourceType != SourceArrayBufferView) {
3913  if (!validateSettableTexFormat(functionName, format))
3914  return false;
3915  }
3916  } else {
3917  if (!validateSettableTexFormat(functionName, format))
3918  return false;
3919  if (!validateSize(functionName, xoffset, yoffset))
3920  return false;
3921  // Before checking if it is in the range, check if overflow happens first.
3922  if (xoffset + width < 0 || yoffset + height < 0) {
3923  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "bad dimensions");
3924  return false;
3925  }
3926  if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) {
3927  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
3928  return false;
3929  }
3930  if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) {
3931  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
3932  return false;
3933  }
3934  }
3935 
3936  return true;
3937 }
3938 
3939 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3940  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3941  GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3942 {
3943  if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed)
3944  || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
3945  return;
3946  void* data = pixels ? pixels->baseAddress() : 0;
3947  Vector<uint8_t> tempData;
3948  bool changeUnpackAlignment = false;
3949  if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3950  if (!m_context->extractTextureData(width, height, format, type,
3951  m_unpackAlignment,
3952  m_unpackFlipY, m_unpackPremultiplyAlpha,
3953  data,
3954  tempData))
3955  return;
3956  data = tempData.data();
3957  changeUnpackAlignment = true;
3958  }
3959  if (changeUnpackAlignment)
3960  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3961  texImage2DBase(target, level, internalformat, width, height, border,
3962  format, type, data, ec);
3963  if (changeUnpackAlignment)
3964  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3965 }
3966 
3967 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3968  GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3969 {
3970  ec = 0;
3971  if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
3972  return;
3973  Vector<uint8_t> data;
3974  bool needConversion = true;
3975  // The data from ImageData is always of format RGBA8.
3976  // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
3977  if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
3978  needConversion = false;
3979  else {
3980  if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3981  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3982  return;
3983  }
3984  }
3985  if (m_unpackAlignment != 1)
3986  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3987  texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
3988  if (m_unpackAlignment != 1)
3989  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3990 }
3991 
3992 PassRefPtr<Image> WebGLRenderingContext::drawImageIntoBuffer(Image* image, int width, int height, int deviceScaleFactor)
3993 {
3994  IntSize size(width, height);
3995  size.scale(deviceScaleFactor);
3996  ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
3997  if (!buf) {
3998  synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
3999  return nullptr;
4000  }
4001 
4002  FloatRect srcRect(FloatPoint(), image->size());
4003  FloatRect destRect(FloatPoint(), size);
4004  buf->context()->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect);
4005  return buf->copyImage(ImageBuffer::fastCopyImageMode());
4006 }
4007 
4008 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
4009  GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
4010 {
4011  ec = 0;
4012  if (isContextLostOrPending() || !validateHTMLImageElement("texImage2D", image, ec))
4013  return;
4014 
4015  RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
4016  if (imageForRender->isSVGImage())
4017  imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
4018 
4019  if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
4020  return;
4021 
4022  texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4023 }
4024 
4025 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
4026  GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
4027 {
4028  ec = 0;
4029  if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
4030  return;
4031 
4032  WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
4033  // If possible, copy from the canvas element directly to the texture
4034  // via the GPU, without a read-back to system memory.
4035  //
4036  // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when
4037  // ImageBuffer::copyToPlatformTexture implementations are fully functional.
4038  if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level)
4039  && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) && type == GraphicsContext3D::UNSIGNED_BYTE) {
4040  ImageBuffer* buffer = canvas->buffer();
4041  if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
4042  texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
4043  return;
4044  }
4045  }
4046 
4047  RefPtr<ImageData> imageData = canvas->getImageData();
4048  if (imageData)
4049  texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
4050  else
4051  texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4052 }
4053 
4054 #if ENABLE(VIDEO)
4055 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy, ExceptionCode&)
4056 {
4057  IntSize size(video->videoWidth(), video->videoHeight());
4058  ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
4059  if (!buf) {
4060  synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
4061  return nullptr;
4062  }
4063  IntRect destRect(0, 0, size.width(), size.height());
4064  // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
4065  video->paintCurrentFrameInContext(buf->context(), destRect);
4066  return buf->copyImage(backingStoreCopy);
4067 }
4068 
4069 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
4070  GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
4071 {
4072  ec = 0;
4073  if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video, ec)
4074  || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
4075  return;
4076 
4077  // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
4078  // Otherwise, it will fall back to the normal SW path.
4079  // FIXME: The current restrictions require that format shoud be RGB or RGBA,
4080  // type should be UNSIGNED_BYTE and level should be 0. It may be lifted in the future.
4081  WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
4082  if (GraphicsContext3D::TEXTURE_2D == target && texture
4083  && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
4084  && type == GraphicsContext3D::UNSIGNED_BYTE
4085  && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level))
4086  && !level) {
4087  if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
4088  texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
4089  return;
4090  }
4091  }
4092 
4093  // Normal pure SW path.
4094  RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
4095  if (!image)
4096  return;
4097  texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4098 }
4099 #endif
4100 
4101 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
4102 {
4103  if (isContextLostOrPending())
4104  return;
4105  WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
4106  if (!tex)
4107  return;
4108  switch (pname) {
4109  case GraphicsContext3D::TEXTURE_MIN_FILTER:
4110  case GraphicsContext3D::TEXTURE_MAG_FILTER:
4111  break;
4112  case GraphicsContext3D::TEXTURE_WRAP_S:
4113  case GraphicsContext3D::TEXTURE_WRAP_T:
4114  if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
4115  || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
4116  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter");
4117  return;
4118  }
4119  break;
4120  case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
4121  if (!m_extTextureFilterAnisotropic) {
4122  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled");
4123  return;
4124  }
4125  break;
4126  default:
4127  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name");
4128  return;
4129  }
4130  if (isFloat) {
4131  tex->setParameterf(pname, paramf);
4132  m_context->texParameterf(target, pname, paramf);
4133  } else {
4134  tex->setParameteri(pname, parami);
4135  m_context->texParameteri(target, pname, parami);
4136  }
4137 }
4138 
4139 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
4140 {
4141  texParameter(target, pname, param, 0, true);
4142 }
4143 
4144 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
4145 {
4146  texParameter(target, pname, 0, param, false);
4147 }
4148 
4149 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
4150 {
4151  // FIXME: For now we ignore any errors returned
4152  ec = 0;
4153  ASSERT(!isContextLost());
4154  ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type));
4155  ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
4156  ASSERT(validateSettableTexFormat("texSubImage2D", format));
4157  WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
4158  if (!tex) {
4159  ASSERT_NOT_REACHED();
4160  return;
4161  }
4162  ASSERT((xoffset + width) >= 0);
4163  ASSERT((yoffset + height) >= 0);
4164  ASSERT(tex->getWidth(target, level) >= (xoffset + width));
4165  ASSERT(tex->getHeight(target, level) >= (yoffset + height));
4166  ASSERT(tex->getInternalFormat(target, level) == format);
4167  ASSERT(tex->getType(target, level) == type);
4168  m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
4169 }
4170 
4171 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
4172 {
4173  ec = 0;
4174  Vector<uint8_t> data;
4175  GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
4176  if (!imageExtractor.extractSucceeded()) {
4177  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
4178  return;
4179  }
4180  GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
4181  GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
4182  const void* imagePixelData = imageExtractor.imagePixelData();
4183 
4184  bool needConversion = true;
4185  if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
4186  needConversion = false;
4187  else {
4188  if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
4189  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
4190  return;
4191  }
4192  }
4193 
4194  if (m_unpackAlignment != 1)
4195  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
4196  texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, ec);
4197  if (m_unpackAlignment != 1)
4198  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
4199 }
4200 
4201 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4202  GC3Dsizei width, GC3Dsizei height,
4203  GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
4204 {
4205  if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed)
4206  || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
4207  return;
4208  void* data = pixels->baseAddress();
4209  Vector<uint8_t> tempData;
4210  bool changeUnpackAlignment = false;
4211  if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
4212  if (!m_context->extractTextureData(width, height, format, type,
4213  m_unpackAlignment,
4214  m_unpackFlipY, m_unpackPremultiplyAlpha,
4215  data,
4216  tempData))
4217  return;
4218  data = tempData.data();
4219  changeUnpackAlignment = true;
4220  }
4221  if (changeUnpackAlignment)
4222  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
4223  texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
4224  if (changeUnpackAlignment)
4225  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
4226 }
4227 
4228 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4229  GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
4230 {
4231  ec = 0;
4232  if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
4233  return;
4234 
4235  Vector<uint8_t> data;
4236  bool needConversion = true;
4237  // The data from ImageData is always of format RGBA8.
4238  // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
4239  if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
4240  needConversion = false;
4241  else {
4242  if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
4243  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
4244  return;
4245  }
4246  }
4247  if (m_unpackAlignment != 1)
4248  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
4249  texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
4250  if (m_unpackAlignment != 1)
4251  m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
4252 }
4253 
4254 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4255  GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
4256 {
4257  ec = 0;
4258  if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
4259  return;
4260 
4261  RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
4262  if (imageForRender->isSVGImage())
4263  imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
4264 
4265  if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
4266  return;
4267 
4268  texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4269 }
4270 
4271 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4272  GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
4273 {
4274  ec = 0;
4275  if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
4276  || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
4277  return;
4278 
4279  RefPtr<ImageData> imageData = canvas->getImageData();
4280  if (imageData)
4281  texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
4282  else
4283  texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4284 }
4285 
4286 #if ENABLE(VIDEO)
4287 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4288  GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
4289 {
4290  ec = 0;
4291  if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
4292  || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
4293  return;
4294 
4295  RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
4296  if (!image)
4297  return;
4298  texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
4299 }
4300 #endif
4301 
4302 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
4303 {
4304  UNUSED_PARAM(ec);
4305  if (isContextLostOrPending() || !location)
4306  return;
4307 
4308  if (location->program() != m_currentProgram) {
4309  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program");
4310  return;
4311  }
4312 
4313  m_context->uniform1f(location->location(), x);
4314 }
4315 
4316 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4317 {
4318  UNUSED_PARAM(ec);
4319  if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, 1))
4320  return;
4321 
4322  m_context->uniform1fv(location->location(), v->length(), v->data());
4323 }
4324 
4325 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4326 {
4327  UNUSED_PARAM(ec);
4328  if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, size, 1))
4329  return;
4330 
4331  m_context->uniform1fv(location->location(), size, v);
4332 }
4333 
4334 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
4335 {
4336  UNUSED_PARAM(ec);
4337  if (isContextLostOrPending() || !location)
4338  return;
4339 
4340  if (location->program() != m_currentProgram) {
4341  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program");
4342  return;
4343  }
4344 
4345  if ((location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) && x >= (int)m_textureUnits.size()) {
4346  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1i", "invalid texture unit");
4347  return;
4348  }
4349 
4350  m_context->uniform1i(location->location(), x);
4351 }
4352 
4353 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4354 {
4355  UNUSED_PARAM(ec);
4356  if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, 1))
4357  return;
4358 
4359  if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE)
4360  for (unsigned i = 0; i < v->length(); ++i) {
4361  if (v->data()[i] >= static_cast<int>(m_textureUnits.size())) {
4362  LOG(WebGL, "Texture unit size=%zu, v[%d]=%d. Location type = %04X.", m_textureUnits.size(), i, v->data()[i], location->type());
4363  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
4364  return;
4365  }
4366  }
4367 
4368  m_context->uniform1iv(location->location(), v->length(), v->data());
4369 }
4370 
4371 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4372 {
4373  UNUSED_PARAM(ec);
4374  if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, size, 1))
4375  return;
4376 
4377  if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE)
4378  for (unsigned i = 0; i < static_cast<unsigned>(size); ++i) {
4379  if (((GC3Dint*)v)[i] >= static_cast<int>(m_textureUnits.size())) {
4380  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
4381  return;
4382  }
4383  }
4384 
4385  m_context->uniform1iv(location->location(), size, v);
4386 }
4387 
4388 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
4389 {
4390  UNUSED_PARAM(ec);
4391  if (isContextLostOrPending() || !location)
4392  return;
4393 
4394  if (location->program() != m_currentProgram) {
4395  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program");
4396  return;
4397  }
4398 
4399  m_context->uniform2f(location->location(), x, y);
4400 }
4401 
4402 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4403 {
4404  UNUSED_PARAM(ec);
4405  if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, 2))
4406  return;
4407 
4408  m_context->uniform2fv(location->location(), v->length() / 2, v->data());
4409 }
4410 
4411 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4412 {
4413  UNUSED_PARAM(ec);
4414  if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, size, 2))
4415  return;
4416 
4417  m_context->uniform2fv(location->location(), size / 2, v);
4418 }
4419 
4420 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
4421 {
4422  UNUSED_PARAM(ec);
4423  if (isContextLostOrPending() || !location)
4424  return;
4425 
4426  if (location->program() != m_currentProgram) {
4427  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program");
4428  return;
4429  }
4430 
4431  m_context->uniform2i(location->location(), x, y);
4432 }
4433 
4434 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4435 {
4436  UNUSED_PARAM(ec);
4437  if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, 2))
4438  return;
4439 
4440  m_context->uniform2iv(location->location(), v->length() / 2, v->data());
4441 }
4442 
4443 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4444 {
4445  UNUSED_PARAM(ec);
4446  if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, size, 2))
4447  return;
4448 
4449  m_context->uniform2iv(location->location(), size / 2, v);
4450 }
4451 
4452 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
4453 {
4454  UNUSED_PARAM(ec);
4455  if (isContextLostOrPending() || !location)
4456  return;
4457 
4458  if (location->program() != m_currentProgram) {
4459  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program");
4460  return;
4461  }
4462 
4463  m_context->uniform3f(location->location(), x, y, z);
4464 }
4465 
4466 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4467 {
4468  UNUSED_PARAM(ec);
4469  if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, 3))
4470  return;
4471 
4472  m_context->uniform3fv(location->location(), v->length() / 3, v->data());
4473 }
4474 
4475 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4476 {
4477  UNUSED_PARAM(ec);
4478  if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, size, 3))
4479  return;
4480 
4481  m_context->uniform3fv(location->location(), size / 3, v);
4482 }
4483 
4484 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
4485 {
4486  UNUSED_PARAM(ec);
4487  if (isContextLostOrPending() || !location)
4488  return;
4489 
4490  if (location->program() != m_currentProgram) {
4491  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program");
4492  return;
4493  }
4494 
4495  m_context->uniform3i(location->location(), x, y, z);
4496 }
4497 
4498 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4499 {
4500  UNUSED_PARAM(ec);
4501  if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, 3))
4502  return;
4503 
4504  m_context->uniform3iv(location->location(), v->length() / 3, v->data());
4505 }
4506 
4507 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4508 {
4509  UNUSED_PARAM(ec);
4510  if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, size, 3))
4511  return;
4512 
4513  m_context->uniform3iv(location->location(), size / 3, v);
4514 }
4515 
4516 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
4517 {
4518  UNUSED_PARAM(ec);
4519  if (isContextLostOrPending() || !location)
4520  return;
4521 
4522  if (location->program() != m_currentProgram) {
4523  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program");
4524  return;
4525  }
4526 
4527  m_context->uniform4f(location->location(), x, y, z, w);
4528 }
4529 
4530 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4531 {
4532  UNUSED_PARAM(ec);
4533  if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, 4))
4534  return;
4535 
4536  m_context->uniform4fv(location->location(), v->length() / 4, v->data());
4537 }
4538 
4539 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4540 {
4541  UNUSED_PARAM(ec);
4542  if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, size, 4))
4543  return;
4544 
4545  m_context->uniform4fv(location->location(), size / 4, v);
4546 }
4547 
4548 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
4549 {
4550  UNUSED_PARAM(ec);
4551  if (isContextLostOrPending() || !location)
4552  return;
4553 
4554  if (location->program() != m_currentProgram) {
4555  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program");
4556  return;
4557  }
4558 
4559  m_context->uniform4i(location->location(), x, y, z, w);
4560 }
4561 
4562 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4563 {
4564  UNUSED_PARAM(ec);
4565  if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, 4))
4566  return;
4567 
4568  m_context->uniform4iv(location->location(), v->length() / 4, v->data());
4569 }
4570 
4571 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4572 {
4573  UNUSED_PARAM(ec);
4574  if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, size, 4))
4575  return;
4576 
4577  m_context->uniform4iv(location->location(), size / 4, v);
4578 }
4579 
4580 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4581 {
4582  UNUSED_PARAM(ec);
4583  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
4584  return;
4585  m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data());
4586 }
4587 
4588 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4589 {
4590  UNUSED_PARAM(ec);
4591  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
4592  return;
4593  m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
4594 }
4595 
4596 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4597 {
4598  UNUSED_PARAM(ec);
4599  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
4600  return;
4601  m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data());
4602 }
4603 
4604 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4605 {
4606  UNUSED_PARAM(ec);
4607  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
4608  return;
4609  m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
4610 }
4611 
4612 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4613 {
4614  UNUSED_PARAM(ec);
4615  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
4616  return;
4617  m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data());
4618 }
4619 
4620 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4621 {
4622  UNUSED_PARAM(ec);
4623  if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
4624  return;
4625  m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
4626 }
4627 
4628 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
4629 {
4630  UNUSED_PARAM(ec);
4631  bool deleted;
4632  if (!checkObjectToBeBound("useProgram", program, deleted))
4633  return;
4634  if (deleted)
4635  program = 0;
4636  if (program && !program->getLinkStatus()) {
4637  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid");
4638  return;
4639  }
4640  if (m_currentProgram != program) {
4641  if (m_currentProgram)
4642  m_currentProgram->onDetached(graphicsContext3D());
4643  m_currentProgram = program;
4644  m_context->useProgram(objectOrZero(program));
4645  if (program)
4646  program->onAttached();
4647  }
4648 }
4649 
4650 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
4651 {
4652  UNUSED_PARAM(ec);
4653  if (isContextLostOrPending() || !validateWebGLObject("validateProgram", program))
4654  return;
4655  m_context->validateProgram(objectOrZero(program));
4656 }
4657 
4658 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
4659 {
4660  vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
4661 }
4662 
4663 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
4664 {
4665  vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
4666 }
4667 
4668 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4669 {
4670  vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
4671 }
4672 
4673 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
4674 {
4675  vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
4676 }
4677 
4678 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
4679 {
4680  vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
4681 }
4682 
4683 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4684 {
4685  vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
4686 }
4687 
4688 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
4689 {
4690  vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
4691 }
4692 
4693 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
4694 {
4695  vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
4696 }
4697 
4698 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4699 {
4700  vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
4701 }
4702 
4703 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
4704 {
4705  vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
4706 }
4707 
4708 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
4709 {
4710  vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
4711 }
4712 
4713 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4714 {
4715  vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
4716 }
4717 
4718 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
4719 {
4720  UNUSED_PARAM(ec);
4721  if (isContextLostOrPending())
4722  return;
4723  switch (type) {
4724  case GraphicsContext3D::BYTE:
4725  case GraphicsContext3D::UNSIGNED_BYTE:
4726  case GraphicsContext3D::SHORT:
4727  case GraphicsContext3D::UNSIGNED_SHORT:
4728  case GraphicsContext3D::FLOAT:
4729  break;
4730  default:
4731  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4732  return;
4733  }
4734  if (index >= m_maxVertexAttribs) {
4735  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range");
4736  return;
4737  }
4738  if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
4739  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset");
4740  return;
4741  }
4742  if (!m_boundArrayBuffer) {
4743  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER");
4744  return;
4745  }
4746  // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
4747  unsigned int typeSize = sizeInBytes(type);
4748  if (!typeSize) {
4749  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4750  return;
4751  }
4752  if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
4753  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type");
4754  return;
4755  }
4756  GC3Dsizei bytesPerElement = size * typeSize;
4757 
4758  m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer);
4759  m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
4760 }
4761 
4762 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
4763 {
4764  if (isContextLostOrPending())
4765  return;
4766  if (!validateSize("viewport", width, height))
4767  return;
4768  m_context->viewport(x, y, width, height);
4769 }
4770 
4771 void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
4772 {
4773  if (isContextLostOrPending()) {
4774  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost");
4775  return;
4776  }
4777 
4778  m_contextGroup->loseContextGroup(mode);
4779 }
4780 
4781 void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode)
4782 {
4783  if (isContextLost())
4784  return;
4785 
4786  m_contextLost = true;
4787  m_contextLostMode = mode;
4788 
4789  if (mode == RealLostContext) {
4790  // Inform the embedder that a lost context was received. In response, the embedder might
4791  // decide to take action such as asking the user for permission to use WebGL again.
4792  if (Frame* frame = canvas()->document().frame())
4793  frame->loader().client().didLoseWebGLContext(m_context->getExtensions()->getGraphicsResetStatusARB());
4794  }
4795 
4796  detachAndRemoveAllObjects();
4797 
4798  if (m_drawingBuffer) {
4799  // Make absolutely sure we do not refer to an already-deleted texture or framebuffer.
4800  m_drawingBuffer->setTexture2DBinding(0);
4801  m_drawingBuffer->setFramebufferBinding(0);
4802  }
4803 
4804  // There is no direct way to clear errors from a GL implementation and
4805  // looping until getError() becomes NO_ERROR might cause an infinite loop if
4806  // the driver or context implementation had a bug. So, loop a reasonably
4807  // large number of times to clear any existing errors.
4808  for (int i = 0; i < 100; ++i) {
4809  if (m_context->getError() == GraphicsContext3D::NO_ERROR)
4810  break;
4811  }
4812  ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole;
4813  synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost", display);
4814 
4815  // Don't allow restoration unless the context lost event has both been
4816  // dispatched and its default behavior prevented.
4817  m_restoreAllowed = false;
4818 
4819  // Always defer the dispatch of the context lost event, to implement
4820  // the spec behavior of queueing a task.
4821  m_dispatchContextLostEventTimer.startOneShot(0);
4822 }
4823 
4824 void WebGLRenderingContext::forceRestoreContext()
4825 {
4826  if (!isContextLostOrPending()) {
4827  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost");
4828  return;
4829  }
4830 
4831  if (!m_restoreAllowed) {
4832  if (m_contextLostMode == SyntheticLostContext)
4833  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed");
4834  return;
4835  }
4836 
4837  if (!m_restoreTimer.isActive())
4838  m_restoreTimer.startOneShot(0);
4839 }
4840 
4841 PlatformLayer* WebGLRenderingContext::platformLayer() const
4842 {
4843  return (!isContextLost() && !m_isPendingPolicyResolution) ? m_context->platformLayer() : 0;
4844 }
4845 
4846 void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
4847 {
4848  if (m_isPendingPolicyResolution)
4849  return;
4850 
4851  m_contextGroup->removeObject(object);
4852 }
4853 
4854 void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object)
4855 {
4856  if (m_isPendingPolicyResolution)
4857  return;
4858 
4859  ASSERT(!isContextLost());
4860  m_contextGroup->addObject(object);
4861 }
4862 
4863 void WebGLRenderingContext::removeContextObject(WebGLContextObject* object)
4864 {
4865  if (m_isPendingPolicyResolution)
4866  return;
4867 
4868  m_contextObjects.remove(object);
4869 }
4870 
4871 void WebGLRenderingContext::addContextObject(WebGLContextObject* object)
4872 {
4873  if (m_isPendingPolicyResolution)
4874  return;
4875 
4876  ASSERT(!isContextLost());
4877  m_contextObjects.add(object);
4878 }
4879 
4880 void WebGLRenderingContext::detachAndRemoveAllObjects()
4881 {
4882  if (m_isPendingPolicyResolution)
4883  return;
4884 
4885  while (m_contextObjects.size() > 0) {
4886  HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
4887  (*it)->detachContext();
4888  }
4889 }
4890 
4891 bool WebGLRenderingContext::hasPendingActivity() const
4892 {
4893  return false;
4894 }
4895 
4896 void WebGLRenderingContext::stop()
4897 {
4898  if (!isContextLost() && !m_isPendingPolicyResolution) {
4899  forceLostContext(SyntheticLostContext);
4900  destroyGraphicsContext3D();
4901  }
4902 }
4903 
4904 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
4905 {
4906  GC3Dboolean value = 0;
4907  m_context->getBooleanv(pname, &value);
4908  return WebGLGetInfo(static_cast<bool>(value));
4909 }
4910 
4911 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
4912 {
4913  if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
4914  notImplemented();
4915  return WebGLGetInfo(0, 0);
4916  }
4917  GC3Dboolean value[4] = {0};
4918  m_context->getBooleanv(pname, value);
4919  bool boolValue[4];
4920  for (int ii = 0; ii < 4; ++ii)
4921  boolValue[ii] = static_cast<bool>(value[ii]);
4922  return WebGLGetInfo(boolValue, 4);
4923 }
4924 
4925 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
4926 {
4927  GC3Dfloat value = 0;
4928  m_context->getFloatv(pname, &value);
4929  return WebGLGetInfo(value);
4930 }
4931 
4932 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
4933 {
4934  GC3Dint value = 0;
4935  m_context->getIntegerv(pname, &value);
4936  return WebGLGetInfo(value);
4937 }
4938 
4939 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
4940 {
4941  GC3Dint value = 0;
4942  m_context->getIntegerv(pname, &value);
4943  return WebGLGetInfo(static_cast<unsigned int>(value));
4944 }
4945 
4946 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
4947 {
4948  GC3Dfloat value[4] = {0};
4949  m_context->getFloatv(pname, value);
4950  unsigned length = 0;
4951  switch (pname) {
4952  case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4953  case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4954  case GraphicsContext3D::DEPTH_RANGE:
4955  length = 2;
4956  break;
4957  case GraphicsContext3D::BLEND_COLOR:
4958  case GraphicsContext3D::COLOR_CLEAR_VALUE:
4959  length = 4;
4960  break;
4961  default:
4962  notImplemented();
4963  }
4964  return WebGLGetInfo(Float32Array::create(value, length));
4965 }
4966 
4967 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4968 {
4969  GC3Dint value[4] = {0};
4970  m_context->getIntegerv(pname, value);
4971  unsigned length = 0;
4972  switch (pname) {
4973  case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4974  length = 2;
4975  break;
4976  case GraphicsContext3D::SCISSOR_BOX:
4977  case GraphicsContext3D::VIEWPORT:
4978  length = 4;
4979  break;
4980  default:
4981  notImplemented();
4982  }
4983  return WebGLGetInfo(Int32Array::create(value, length));
4984 }
4985 
4986 void WebGLRenderingContext::checkTextureCompleteness(const char* functionName, bool prepareToDraw)
4987 {
4988  bool resetActiveUnit = false;
4989  WebGLTexture::TextureExtensionFlag extensions = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0));
4990 
4991  for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
4992  if ((m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
4993  || (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))) {
4994  if (ii != m_activeTextureUnit) {
4995  m_context->activeTexture(ii);
4996  resetActiveUnit = true;
4997  } else if (resetActiveUnit) {
4998  m_context->activeTexture(ii);
4999  resetActiveUnit = false;
5000  }
5001  WebGLTexture* tex2D;
5002  WebGLTexture* texCubeMap;
5003  if (prepareToDraw) {
5004  String msg(String("texture bound to texture unit ") + String::number(ii)
5005  + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete',"
5006  + " or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled.");
5007  printGLWarningToConsole(functionName, msg.utf8().data());
5008  tex2D = m_blackTexture2D.get();
5009  texCubeMap = m_blackTextureCubeMap.get();
5010  } else {
5011  tex2D = m_textureUnits[ii].texture2DBinding.get();
5012  texCubeMap = m_textureUnits[ii].textureCubeMapBinding.get();
5013  }
5014  if (m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
5015  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
5016  if (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))
5017  m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
5018  }
5019  }
5020  if (resetActiveUnit)
5021  m_context->activeTexture(m_activeTextureUnit);
5022 }
5023 
5024 void WebGLRenderingContext::createFallbackBlackTextures1x1()
5025 {
5026  unsigned char black[] = {0, 0, 0, 255};
5027  m_blackTexture2D = createTexture();
5028  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
5029  m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
5030  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5031  m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
5032  m_blackTextureCubeMap = createTexture();
5033  m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
5034  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
5035  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5036  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
5037  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5038  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
5039  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5040  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
5041  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5042  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
5043  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5044  m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
5045  0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
5046  m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
5047 }
5048 
5049 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
5050  GC3Denum colorBufferFormat)
5051 {
5052  unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
5053  unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
5054  return (need & have) == need;
5055 }
5056 
5057 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
5058 {
5059  if (m_framebufferBinding && m_framebufferBinding->object())
5060  return m_framebufferBinding->getColorBufferFormat();
5061  if (m_attributes.alpha)
5062  return GraphicsContext3D::RGBA;
5063  return GraphicsContext3D::RGB;
5064 }
5065 
5066 int WebGLRenderingContext::getBoundFramebufferWidth()
5067 {
5068  if (m_framebufferBinding && m_framebufferBinding->object())
5069  return m_framebufferBinding->getColorBufferWidth();
5070  return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width();
5071 }
5072 
5073 int WebGLRenderingContext::getBoundFramebufferHeight()
5074 {
5075  if (m_framebufferBinding && m_framebufferBinding->object())
5076  return m_framebufferBinding->getColorBufferHeight();
5077  return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height();
5078 }
5079 
5080 WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap)
5081 {
5082  WebGLTexture* texture = nullptr;
5083  switch (target) {
5084  case GraphicsContext3D::TEXTURE_2D:
5085  texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get();
5086  break;
5087  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
5088  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
5089  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
5090  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
5091  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
5092  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
5093  if (!useSixEnumsForCubeMap) {
5094  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
5095  return nullptr;
5096  }
5097  texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
5098  break;
5099  case GraphicsContext3D::TEXTURE_CUBE_MAP:
5100  if (useSixEnumsForCubeMap) {
5101  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
5102  return nullptr;
5103  }
5104  texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
5105  break;
5106  default:
5107  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
5108  return nullptr;
5109  }
5110  if (!texture)
5111  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture");
5112  return texture;
5113 }
5114 
5115 bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string)
5116 {
5117  const unsigned maxWebGLLocationLength = 256;
5118  if (string.length() > maxWebGLLocationLength) {
5119  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256");
5120  return false;
5121  }
5122  return true;
5123 }
5124 
5125 bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y)
5126 {
5127  if (x < 0 || y < 0) {
5128  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
5129  return false;
5130  }
5131  return true;
5132 }
5133 
5134 bool WebGLRenderingContext::validateString(const char* functionName, const String& string)
5135 {
5136  for (size_t i = 0; i < string.length(); ++i) {
5137  if (!validateCharacter(string[i])) {
5138  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII");
5139  return false;
5140  }
5141  }
5142  return true;
5143 }
5144 
5145 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
5146 {
5147  switch (format) {
5148  case GraphicsContext3D::ALPHA:
5149  case GraphicsContext3D::LUMINANCE:
5150  case GraphicsContext3D::LUMINANCE_ALPHA:
5151  case GraphicsContext3D::RGB:
5152  case GraphicsContext3D::RGBA:
5153  break;
5154  case GraphicsContext3D::DEPTH_STENCIL:
5155  case GraphicsContext3D::DEPTH_COMPONENT:
5156  if (m_webglDepthTexture)
5157  break;
5158  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
5159  return false;
5160  case Extensions3D::SRGB_EXT:
5161  case Extensions3D::SRGB_ALPHA_EXT:
5162  default:
5163  if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
5164  && m_extsRGB)
5165  break;
5166  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
5167  return false;
5168  }
5169 
5170  switch (type) {
5171  case GraphicsContext3D::UNSIGNED_BYTE:
5172  case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
5173  case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
5174  case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
5175  break;
5176  case GraphicsContext3D::FLOAT:
5177  if (m_oesTextureFloat)
5178  break;
5179  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5180  return false;
5181  case GraphicsContext3D::HALF_FLOAT_OES:
5182  if (m_oesTextureHalfFloat)
5183  break;
5184  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5185  return false;
5186  case GraphicsContext3D::UNSIGNED_INT:
5187  case GraphicsContext3D::UNSIGNED_INT_24_8:
5188  case GraphicsContext3D::UNSIGNED_SHORT:
5189  if (m_webglDepthTexture)
5190  break;
5191  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5192  return false;
5193  default:
5194  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
5195  return false;
5196  }
5197 
5198  // Verify that the combination of format and type is supported.
5199  switch (format) {
5200  case GraphicsContext3D::ALPHA:
5201  case GraphicsContext3D::LUMINANCE:
5202  case GraphicsContext3D::LUMINANCE_ALPHA:
5203  if (type != GraphicsContext3D::UNSIGNED_BYTE
5204  && type != GraphicsContext3D::FLOAT
5205  && type != GraphicsContext3D::HALF_FLOAT_OES) {
5206  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
5207  return false;
5208  }
5209  break;
5210  case GraphicsContext3D::RGB:
5211  case Extensions3D::SRGB_EXT:
5212  if (type != GraphicsContext3D::UNSIGNED_BYTE
5213  && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
5214  && type != GraphicsContext3D::FLOAT
5215  && type != GraphicsContext3D::HALF_FLOAT_OES) {
5216  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
5217  return false;
5218  }
5219  break;
5220  case GraphicsContext3D::RGBA:
5221  case Extensions3D::SRGB_ALPHA_EXT:
5222  if (type != GraphicsContext3D::UNSIGNED_BYTE
5223  && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
5224  && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
5225  && type != GraphicsContext3D::FLOAT
5226  && type != GraphicsContext3D::HALF_FLOAT_OES) {
5227  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
5228  return false;
5229  }
5230  break;
5231  case GraphicsContext3D::DEPTH_COMPONENT:
5232  if (!m_webglDepthTexture) {
5233  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
5234  return false;
5235  }
5236  if (type != GraphicsContext3D::UNSIGNED_SHORT
5237  && type != GraphicsContext3D::UNSIGNED_INT) {
5238  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
5239  return false;
5240  }
5241  if (level > 0) {
5242  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
5243  return false;
5244  }
5245  break;
5246  case GraphicsContext3D::DEPTH_STENCIL:
5247  if (!m_webglDepthTexture) {
5248  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
5249  return false;
5250  }
5251  if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
5252  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
5253  return false;
5254  }
5255  if (level > 0) {
5256  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
5257  return false;
5258  }
5259  break;
5260  default:
5261  ASSERT_NOT_REACHED();
5262  }
5263 
5264  return true;
5265 }
5266 
5267 bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
5268 {
5269  if (level < 0) {
5270  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
5271  return false;
5272  }
5273  switch (target) {
5274  case GraphicsContext3D::TEXTURE_2D:
5275  if (level >= m_maxTextureLevel) {
5276  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
5277  return false;
5278  }
5279  break;
5280  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
5281  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
5282  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
5283  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
5284  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
5285  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
5286  if (level >= m_maxCubeMapTextureLevel) {
5287  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
5288  return false;
5289  }
5290  break;
5291  }
5292  // This function only checks if level is legal, so we return true and don't
5293  // generate INVALID_ENUM if target is illegal.
5294  return true;
5295 }
5296 
5297 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
5298  TexFuncValidationFunctionType functionType,
5299  GC3Denum target, GC3Dint level,
5300  GC3Denum internalformat,
5301  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
5302  GC3Denum format, GC3Denum type)
5303 {
5304  // We absolutely have to validate the format and type combination.
5305  // The texImage2D entry points taking HTMLImage, etc. will produce
5306  // temporary data based on this combination, so it must be legal.
5307  if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
5308  return false;
5309 
5310  if (width < 0 || height < 0) {
5311  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
5312  return false;
5313  }
5314 
5315  GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
5316  switch (target) {
5317  case GraphicsContext3D::TEXTURE_2D:
5318  if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
5319  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
5320  return false;
5321  }
5322  break;
5323  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
5324  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
5325  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
5326  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
5327  case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
5328  case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
5329  if (functionType != TexSubImage2D && width != height) {
5330  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
5331  return false;
5332  }
5333  // No need to check height here. For texImage width == height.
5334  // For texSubImage that will be checked when checking yoffset + height is in range.
5335  if (width > maxTextureSizeForLevel) {
5336  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
5337  return false;
5338  }
5339  break;
5340  default:
5341  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5342  return false;
5343  }
5344 
5345  if (format != internalformat) {
5346  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
5347  return false;
5348  }
5349 
5350  if (border) {
5351  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
5352  return false;
5353  }
5354 
5355  return true;
5356 }
5357 
5358 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
5359  GC3Dsizei width, GC3Dsizei height,
5360  GC3Denum format, GC3Denum type,
5361  ArrayBufferView* pixels,
5362  NullDisposition disposition)
5363 {
5364  if (!pixels) {
5365  if (disposition == NullAllowed)
5366  return true;
5367  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
5368  return false;
5369  }
5370 
5371  if (!validateTexFuncFormatAndType(functionName, format, type, level))
5372  return false;
5373  if (!validateSettableTexFormat(functionName, format))
5374  return false;
5375 
5376  switch (type) {
5377  case GraphicsContext3D::UNSIGNED_BYTE:
5378  if (pixels->getType() != JSC::TypeUint8) {
5379  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
5380  return false;
5381  }
5382  break;
5383  case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
5384  case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
5385  case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
5386  if (pixels->getType() != JSC::TypeUint16) {
5387  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
5388  return false;
5389  }
5390  break;
5391  case GraphicsContext3D::FLOAT: // OES_texture_float
5392  if (pixels->getType() != JSC::TypeFloat32) {
5393  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
5394  return false;
5395  }
5396  break;
5397  case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
5398  // As per the specification, ArrayBufferView should be null when
5399  // OES_texture_half_float is enabled.
5400  if (pixels) {
5401  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
5402  return false;
5403  }
5404  break;
5405  default:
5406  ASSERT_NOT_REACHED();
5407  }
5408 
5409  unsigned int totalBytesRequired;
5410  GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
5411  if (error != GraphicsContext3D::NO_ERROR) {
5412  synthesizeGLError(error, functionName, "invalid texture dimensions");
5413  return false;
5414  }
5415  if (pixels->byteLength() < totalBytesRequired) {
5416  if (m_unpackAlignment != 1) {
5417  error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
5418  if (pixels->byteLength() == totalBytesRequired) {
5419  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
5420  return false;
5421  }
5422  }
5423  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
5424  return false;
5425  }
5426  return true;
5427 }
5428 
5429 bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format)
5430 {
5431  return m_compressedTextureFormats.contains(format);
5432 }
5433 
5434 bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName,
5435  GC3Dsizei width, GC3Dsizei height,
5436  GC3Denum format, ArrayBufferView* pixels)
5437 {
5438  if (!pixels) {
5439  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
5440  return false;
5441  }
5442  if (width < 0 || height < 0) {
5443  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
5444  return false;
5445  }
5446 
5447  unsigned int bytesRequired = 0;
5448 
5449  switch (format) {
5450  case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5451  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5452  case Extensions3D::COMPRESSED_ATC_RGB_AMD:
5453  {
5454  const int kBlockSize = 8;
5455  const int kBlockWidth = 4;
5456  const int kBlockHeight = 4;
5457  int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5458  int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5459  bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
5460  }
5461  break;
5462  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5463  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
5464  case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD:
5465  case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
5466  {
5467  const int kBlockSize = 16;
5468  const int kBlockWidth = 4;
5469  const int kBlockHeight = 4;
5470  int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5471  int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5472  bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
5473  }
5474  break;
5475  case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
5476  case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
5477  {
5478  const int kBlockSize = 8;
5479  const int kBlockWidth = 8;
5480  const int kBlockHeight = 8;
5481  bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 4 + 7) / kBlockSize;
5482  }
5483  break;
5484  case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
5485  case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
5486  {
5487  const int kBlockSize = 8;
5488  const int kBlockWidth = 16;
5489  const int kBlockHeight = 8;
5490  bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 2 + 7) / kBlockSize;
5491  }
5492  break;
5493  default:
5494  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format");
5495  return false;
5496  }
5497 
5498  if (pixels->byteLength() != bytesRequired) {
5499  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions");
5500  return false;
5501  }
5502 
5503  return true;
5504 }
5505 
5506 bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format)
5507 {
5508  switch (format) {
5509  case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5510  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5511  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5512  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5513  const GC3Dsizei kBlockWidth = 4;
5514  const GC3Dsizei kBlockHeight = 4;
5515  const GC3Dint maxTextureSize = target ? m_maxTextureSize : m_maxCubeMapTextureSize;
5516  const GC3Dsizei maxCompressedDimension = maxTextureSize >> level;
5517  bool widthValid = (level && width == 1) || (level && width == 2) || (!(width % kBlockWidth) && width <= maxCompressedDimension);
5518  bool heightValid = (level && height == 1) || (level && height == 2) || (!(height % kBlockHeight) && height <= maxCompressedDimension);
5519  if (!widthValid || !heightValid) {
5520  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
5521  return false;
5522  }
5523  return true;
5524  }
5525  case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
5526  case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
5527  case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
5528  case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
5529  // Height and width must be powers of 2.
5530  if ((width & (width - 1)) || (height & (height - 1))) {
5531  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
5532  return false;
5533  }
5534  return true;
5535  default:
5536  return false;
5537  }
5538 }
5539 
5540 bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
5541  GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
5542 {
5543  if (xoffset < 0 || yoffset < 0) {
5544  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
5545  return false;
5546  }
5547 
5548  switch (format) {
5549  case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5550  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5551  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5552  case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5553  const int kBlockWidth = 4;
5554  const int kBlockHeight = 4;
5555  if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
5556  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4");
5557  return false;
5558  }
5559  if (width - xoffset > tex->getWidth(target, level)
5560  || height - yoffset > tex->getHeight(target, level)) {
5561  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range");
5562  return false;
5563  }
5564  return validateCompressedTexDimensions(functionName, target, level, width, height, format);
5565  }
5566  case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
5567  case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
5568  case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
5569  case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
5570  if (xoffset || yoffset) {
5571  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset and yoffset must be zero");
5572  return false;
5573  }
5574  if (width != tex->getWidth(target, level)
5575  || height != tex->getHeight(target, level)) {
5576  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions must match existing level");
5577  return false;
5578  }
5579  return validateCompressedTexDimensions(functionName, target, level, width, height, format);
5580  }
5581  default:
5582  return false;
5583  }
5584 }
5585 
5586 bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode)
5587 {
5588  switch (mode) {
5589  case GraphicsContext3D::POINTS:
5590  case GraphicsContext3D::LINE_STRIP:
5591  case GraphicsContext3D::LINE_LOOP:
5592  case GraphicsContext3D::LINES:
5593  case GraphicsContext3D::TRIANGLE_STRIP:
5594  case GraphicsContext3D::TRIANGLE_FAN:
5595  case GraphicsContext3D::TRIANGLES:
5596  return true;
5597  default:
5598  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode");
5599  return false;
5600  }
5601 }
5602 
5603 bool WebGLRenderingContext::validateStencilSettings(const char* functionName)
5604 {
5605  if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
5606  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match");
5607  return false;
5608  }
5609  return true;
5610 }
5611 
5612 bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Denum func)
5613 {
5614  switch (func) {
5615  case GraphicsContext3D::NEVER:
5616  case GraphicsContext3D::LESS:
5617  case GraphicsContext3D::LEQUAL:
5618  case GraphicsContext3D::GREATER:
5619  case GraphicsContext3D::GEQUAL:
5620  case GraphicsContext3D::EQUAL:
5621  case GraphicsContext3D::NOTEQUAL:
5622  case GraphicsContext3D::ALWAYS:
5623  return true;
5624  default:
5625  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function");
5626  return false;
5627  }
5628 }
5629 
5630 void WebGLRenderingContext::printGLErrorToConsole(const String& message)
5631 {
5632  if (!m_numGLErrorsToConsoleAllowed)
5633  return;
5634 
5635  --m_numGLErrorsToConsoleAllowed;
5636  printWarningToConsole(message);
5637 
5638  if (!m_numGLErrorsToConsoleAllowed)
5639  printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context.");
5640 }
5641 
5642 void WebGLRenderingContext::printWarningToConsole(const String& message)
5643 {
5644  if (!canvas())
5645  return;
5646  canvas()->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Warning, message);
5647 }
5648 
5649 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
5650 {
5651  if (target != GraphicsContext3D::FRAMEBUFFER) {
5652  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5653  return false;
5654  }
5655  switch (attachment) {
5656  case GraphicsContext3D::COLOR_ATTACHMENT0:
5657  case GraphicsContext3D::DEPTH_ATTACHMENT:
5658  case GraphicsContext3D::STENCIL_ATTACHMENT:
5659  case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
5660  break;
5661  default:
5662  if (m_webglDrawBuffers
5663  && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
5664  && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
5665  break;
5666  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
5667  return false;
5668  }
5669  return true;
5670 }
5671 
5672 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
5673 {
5674  switch (mode) {
5675  case GraphicsContext3D::FUNC_ADD:
5676  case GraphicsContext3D::FUNC_SUBTRACT:
5677  case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
5678  case Extensions3D::MIN_EXT:
5679  case Extensions3D::MAX_EXT:
5680  if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) {
5681  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
5682  return false;
5683  }
5684  return true;
5685  break;
5686  default:
5687  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
5688  return false;
5689  }
5690 }
5691 
5692 bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst)
5693 {
5694  if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5695  && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
5696  || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5697  && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
5698  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst");
5699  return false;
5700  }
5701  return true;
5702 }
5703 
5704 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
5705 {
5706  switch (cap) {
5707  case GraphicsContext3D::BLEND:
5708  case GraphicsContext3D::CULL_FACE:
5709  case GraphicsContext3D::DEPTH_TEST:
5710  case GraphicsContext3D::DITHER:
5711  case GraphicsContext3D::POLYGON_OFFSET_FILL:
5712  case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
5713  case GraphicsContext3D::SAMPLE_COVERAGE:
5714  case GraphicsContext3D::SCISSOR_TEST:
5715  case GraphicsContext3D::STENCIL_TEST:
5716  return true;
5717  default:
5718  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
5719  return false;
5720  }
5721 }
5722 
5723 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
5724 {
5725  if (!v) {
5726  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5727  return false;
5728  }
5729  return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5730 }
5731 
5732 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
5733 {
5734  if (!v) {
5735  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5736  return false;
5737  }
5738  return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5739 }
5740 
5741 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5742 {
5743  return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize);
5744 }
5745 
5746 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
5747 {
5748  if (!v) {
5749  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5750  return false;
5751  }
5752  return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize);
5753 }
5754 
5755 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5756 {
5757  if (!location)
5758  return false;
5759  if (location->program() != m_currentProgram) {
5760  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program");
5761  return false;
5762  }
5763  if (!v) {
5764  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5765  return false;
5766  }
5767  if (transpose) {
5768  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE");
5769  return false;
5770  }
5771  if (size < requiredMinSize || (size % requiredMinSize)) {
5772  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5773  return false;
5774  }
5775  return true;
5776 }
5777 
5778 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage)
5779 {
5780  WebGLBuffer* buffer = 0;
5781  switch (target) {
5782  case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
5783  buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
5784  break;
5785  case GraphicsContext3D::ARRAY_BUFFER:
5786  buffer = m_boundArrayBuffer.get();
5787  break;
5788  default:
5789  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5790  return nullptr;
5791  }
5792  if (!buffer) {
5793  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer");
5794  return nullptr;
5795  }
5796  switch (usage) {
5797  case GraphicsContext3D::STREAM_DRAW:
5798  case GraphicsContext3D::STATIC_DRAW:
5799  case GraphicsContext3D::DYNAMIC_DRAW:
5800  return buffer;
5801  }
5802  synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage");
5803  return nullptr;
5804 }
5805 
5806 bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionCode& ec)
5807 {
5808  if (!image || !image->cachedImage()) {
5809  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image");
5810  return false;
5811  }
5812  const URL& url = image->cachedImage()->response().url();
5813  if (url.isNull() || url.isEmpty() || !url.isValid()) {
5814  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image");
5815  return false;
5816  }
5817  if (wouldTaintOrigin(image)) {
5818  ec = SECURITY_ERR;
5819  return false;
5820  }
5821  return true;
5822 }
5823 
5824 bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionCode& ec)
5825 {
5826  if (!canvas || !canvas->buffer()) {
5827  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no canvas");
5828  return false;
5829  }
5830  if (wouldTaintOrigin(canvas)) {
5831  ec = SECURITY_ERR;
5832  return false;
5833  }
5834  return true;
5835 }
5836 
5837 #if ENABLE(VIDEO)
5838 bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionCode& ec)
5839 {
5840  if (!video || !video->videoWidth() || !video->videoHeight()) {
5841  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no video");
5842  return false;
5843  }
5844  if (wouldTaintOrigin(video)) {
5845  ec = SECURITY_ERR;
5846  return false;
5847  }
5848  return true;
5849 }
5850 #endif
5851 
5852 void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
5853 {
5854  if (isContextLostOrPending())
5855  return;
5856  if (index >= m_maxVertexAttribs) {
5857  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5858  return;
5859  }
5860  // In GL, we skip setting vertexAttrib0 values.
5861  if (index || isGLES2Compliant()) {
5862  switch (expectedSize) {
5863  case 1:
5864  m_context->vertexAttrib1f(index, v0);
5865  break;
5866  case 2:
5867  m_context->vertexAttrib2f(index, v0, v1);
5868  break;
5869  case 3:
5870  m_context->vertexAttrib3f(index, v0, v1, v2);
5871  break;
5872  case 4:
5873  m_context->vertexAttrib4f(index, v0, v1, v2, v3);
5874  break;
5875  }
5876  }
5877  VertexAttribValue& attribValue = m_vertexAttribValue[index];
5878  attribValue.value[0] = v0;
5879  attribValue.value[1] = v1;
5880  attribValue.value[2] = v2;
5881  attribValue.value[3] = v3;
5882 }
5883 
5884 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
5885 {
5886  if (isContextLostOrPending())
5887  return;
5888  if (!v) {
5889  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5890  return;
5891  }
5892  vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize);
5893 }
5894 
5895 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
5896 {
5897  if (isContextLostOrPending())
5898  return;
5899  if (!v) {
5900  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5901  return;
5902  }
5903  if (size < expectedSize) {
5904  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5905  return;
5906  }
5907  if (index >= m_maxVertexAttribs) {
5908  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5909  return;
5910  }
5911  // In GL, we skip setting vertexAttrib0 values.
5912  if (index || isGLES2Compliant()) {
5913  switch (expectedSize) {
5914  case 1:
5915  m_context->vertexAttrib1fv(index, v);
5916  break;
5917  case 2:
5918  m_context->vertexAttrib2fv(index, v);
5919  break;
5920  case 3:
5921  m_context->vertexAttrib3fv(index, v);
5922  break;
5923  case 4:
5924  m_context->vertexAttrib4fv(index, v);
5925  break;
5926  }
5927  }
5928  VertexAttribValue& attribValue = m_vertexAttribValue[index];
5929  attribValue.initValue();
5930  for (int ii = 0; ii < expectedSize; ++ii)
5931  attribValue.value[ii] = v[ii];
5932 }
5933 
5934 void WebGLRenderingContext::initVertexAttrib0()
5935 {
5936  WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5937 
5938  m_vertexAttrib0Buffer = createBuffer();
5939  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5940  m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
5941  m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
5942  state.bufferBinding = m_vertexAttrib0Buffer;
5943  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
5944  m_context->enableVertexAttribArray(0);
5945  m_vertexAttrib0BufferSize = 0;
5946  m_vertexAttrib0BufferValue[0] = 0.0f;
5947  m_vertexAttrib0BufferValue[1] = 0.0f;
5948  m_vertexAttrib0BufferValue[2] = 0.0f;
5949  m_vertexAttrib0BufferValue[3] = 1.0f;
5950  m_forceAttrib0BufferRefill = false;
5951  m_vertexAttrib0UsedBefore = false;
5952 }
5953 
5954 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
5955 {
5956  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5957  const VertexAttribValue& attribValue = m_vertexAttribValue[0];
5958  if (!m_currentProgram)
5959  return false;
5960  bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
5961  if (usingVertexAttrib0)
5962  m_vertexAttrib0UsedBefore = true;
5963  if (state.enabled && usingVertexAttrib0)
5964  return false;
5965  if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
5966  return false;
5967  m_vertexAttrib0UsedBefore = true;
5968  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5969  GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
5970  if (bufferDataSize > m_vertexAttrib0BufferSize) {
5971  m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
5972  m_vertexAttrib0BufferSize = bufferDataSize;
5973  m_forceAttrib0BufferRefill = true;
5974  }
5975  if (usingVertexAttrib0
5976  && (m_forceAttrib0BufferRefill
5977  || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
5978  || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
5979  || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
5980  || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
5981  auto bufferData = std::make_unique<GC3Dfloat[]>((numVertex + 1) * 4);
5982  for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
5983  bufferData[ii * 4] = attribValue.value[0];
5984  bufferData[ii * 4 + 1] = attribValue.value[1];
5985  bufferData[ii * 4 + 2] = attribValue.value[2];
5986  bufferData[ii * 4 + 3] = attribValue.value[3];
5987  }
5988  m_vertexAttrib0BufferValue[0] = attribValue.value[0];
5989  m_vertexAttrib0BufferValue[1] = attribValue.value[1];
5990  m_vertexAttrib0BufferValue[2] = attribValue.value[2];
5991  m_vertexAttrib0BufferValue[3] = attribValue.value[3];
5992  m_forceAttrib0BufferRefill = false;
5993  m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
5994  }
5995  m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
5996  return true;
5997 }
5998 
5999 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
6000 {
6001  const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
6002  if (state.bufferBinding != m_vertexAttrib0Buffer) {
6003  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
6004  m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
6005  }
6006  m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
6007 }
6008 
6009 void WebGLRenderingContext::dispatchContextLostEvent()
6010 {
6011  RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
6012  canvas()->dispatchEvent(event);
6013  m_restoreAllowed = event->defaultPrevented();
6014  if (m_contextLostMode == RealLostContext && m_restoreAllowed)
6015  m_restoreTimer.startOneShot(0);
6016 }
6017 
6018 void WebGLRenderingContext::maybeRestoreContext()
6019 {
6020  ASSERT(m_contextLost);
6021  if (!m_contextLost)
6022  return;
6023 
6024  // The rendering context is not restored unless the default behavior of the
6025  // webglcontextlost event was prevented earlier.
6026  //
6027  // Because of the way m_restoreTimer is set up for real vs. synthetic lost
6028  // context events, we don't have to worry about this test short-circuiting
6029  // the retry loop for real context lost events.
6030  if (!m_restoreAllowed)
6031  return;
6032 
6033  int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
6034 
6035  switch (contextLostReason) {
6036  case GraphicsContext3D::NO_ERROR:
6037  // The GraphicsContext3D implementation might not fully
6038  // support GL_ARB_robustness semantics yet. Alternatively, the
6039  // WEBGL_lose_context extension might have been used to force
6040  // a lost context.
6041  break;
6042  case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
6043  // The rendering context is not restored if this context was
6044  // guilty of causing the graphics reset.
6045  printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
6046  return;
6047  case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
6048  // Always allow the context to be restored.
6049  break;
6050  case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
6051  // Warn. Ideally, prompt the user telling them that WebGL
6052  // content on the page might have caused the graphics card to
6053  // reset and ask them whether they want to continue running
6054  // the content. Only if they say "yes" should we start
6055  // attempting to restore the context.
6056  printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
6057  break;
6058  }
6059 
6060  Frame* frame = canvas()->document().frame();
6061  if (!frame)
6062  return;
6063 
6064  if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled()))
6065  return;
6066 
6067  FrameView* view = frame->view();
6068  if (!view)
6069  return;
6070  ScrollView* root = view->root();
6071  if (!root)
6072  return;
6073  HostWindow* hostWindow = root->hostWindow();
6074  if (!hostWindow)
6075  return;
6076 
6077  RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, hostWindow));
6078  if (!context) {
6079  if (m_contextLostMode == RealLostContext)
6080  m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
6081  else
6082  // This likely shouldn't happen but is the best way to report it to the WebGL app.
6083  synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context");
6084  return;
6085  }
6086 
6087  // Construct a new drawing buffer with the new GraphicsContext3D.
6088  if (m_drawingBuffer) {
6089  m_drawingBuffer->discardResources();
6090  DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
6091  DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
6092  m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha);
6093  m_drawingBuffer->bind();
6094  }
6095 
6096  m_context = context;
6097  m_contextLost = false;
6098  setupFlags();
6099  initializeNewContext();
6100  canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
6101 }
6102 
6103 String WebGLRenderingContext::ensureNotNull(const String& text) const
6104 {
6105  if (text.isNull())
6106  return WTF::emptyString();
6107  return text;
6108 }
6109 
6110 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
6111  : m_buffers(std::make_unique<std::unique_ptr<ImageBuffer>[]>(capacity))
6112  , m_capacity(capacity)
6113 {
6114 }
6115 
6116 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
6117 {
6118  int i;
6119  for (i = 0; i < m_capacity; ++i) {
6120  ImageBuffer* buf = m_buffers[i].get();
6121  if (!buf)
6122  break;
6123  if (buf->logicalSize() != size)
6124  continue;
6125  bubbleToFront(i);
6126  return buf;
6127  }
6128 
6129  std::unique_ptr<ImageBuffer> temp = ImageBuffer::create(size, 1);
6130  if (!temp)
6131  return nullptr;
6132  i = std::min(m_capacity - 1, i);
6133  m_buffers[i] = WTF::move(temp);
6134 
6135  ImageBuffer* buf = m_buffers[i].get();
6136  bubbleToFront(i);
6137  return buf;
6138 }
6139 
6140 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
6141 {
6142  for (int i = idx; i > 0; --i)
6143  m_buffers[i].swap(m_buffers[i-1]);
6144 }
6145 
6146 namespace {
6147 
6148  String GetErrorString(GC3Denum error)
6149  {
6150  switch (error) {
6151  case GraphicsContext3D::INVALID_ENUM:
6152  return "INVALID_ENUM";
6153  case GraphicsContext3D::INVALID_VALUE:
6154  return "INVALID_VALUE";
6155  case GraphicsContext3D::INVALID_OPERATION:
6156  return "INVALID_OPERATION";
6157  case GraphicsContext3D::OUT_OF_MEMORY:
6158  return "OUT_OF_MEMORY";
6159  case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
6160  return "INVALID_FRAMEBUFFER_OPERATION";
6161  case GraphicsContext3D::CONTEXT_LOST_WEBGL:
6162  return "CONTEXT_LOST_WEBGL";
6163  default:
6164  return String::format("WebGL ERROR(%04x)", error);
6165  }
6166  }
6167 
6168 } // namespace anonymous
6169 
6170 void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display)
6171 {
6172  if (m_synthesizedErrorsToConsole && display == DisplayInConsole) {
6173  String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description);
6174  printGLErrorToConsole(str);
6175  }
6176  m_context->synthesizeGLError(error);
6177 }
6178 
6179 
6180 void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description)
6181 {
6182  if (m_synthesizedErrorsToConsole) {
6183  String str = String("WebGL: ") + String(functionName) + ": " + String(description);
6184  printGLErrorToConsole(str);
6185  }
6186 }
6187 
6188 void WebGLRenderingContext::applyStencilTest()
6189 {
6190  bool haveStencilBuffer = false;
6191 
6192  if (m_framebufferBinding)
6193  haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
6194  else {
6195  RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
6196  haveStencilBuffer = attributes->stencil();
6197  }
6198  enableOrDisable(GraphicsContext3D::STENCIL_TEST,
6199  m_stencilEnabled && haveStencilBuffer);
6200 }
6201 
6202 void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable)
6203 {
6204  if (enable)
6205  m_context->enable(capability);
6206  else
6207  m_context->disable(capability);
6208 }
6209 
6210 IntSize WebGLRenderingContext::clampedCanvasSize()
6211 {
6212  return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
6213  clamp(canvas()->height(), 1, m_maxViewportDims[1]));
6214 }
6215 
6216 GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
6217 {
6218  if (!supportsDrawBuffers())
6219  return 0;
6220  if (!m_maxDrawBuffers)
6221  m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
6222  if (!m_maxColorAttachments)
6223  m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
6224  // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
6225  return std::min(m_maxDrawBuffers, m_maxColorAttachments);
6226 }
6227 
6228 GC3Dint WebGLRenderingContext::getMaxColorAttachments()
6229 {
6230  if (!supportsDrawBuffers())
6231  return 0;
6232  if (!m_maxColorAttachments)
6233  m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
6234  return m_maxColorAttachments;
6235 }
6236 
6237 void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf)
6238 {
6239  m_backDrawBuffer = buf;
6240 }
6241 
6242 void WebGLRenderingContext::restoreCurrentFramebuffer()
6243 {
6244  ExceptionCode ec;
6245  bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get(), ec);
6246 }
6247 
6248 void WebGLRenderingContext::restoreCurrentTexture2D()
6249 {
6250  ExceptionCode ec;
6251  bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUnit].texture2DBinding.get(), ec);
6252 }
6253 
6254 bool WebGLRenderingContext::supportsDrawBuffers()
6255 {
6256  if (!m_drawBuffersWebGLRequirementsChecked) {
6257  m_drawBuffersWebGLRequirementsChecked = true;
6258  m_drawBuffersSupported = WebGLDrawBuffers::supported(this);
6259  }
6260  return m_drawBuffersSupported;
6261 }
6262 
6263 void WebGLRenderingContext::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
6264 {
6265  if (!primcount) {
6266  markContextChanged();
6267  return;
6268  }
6269 
6270  if (!validateDrawArrays("drawArraysInstanced", mode, first, count, primcount))
6271  return;
6272 
6273  clearIfComposited();
6274 
6275  bool vertexAttrib0Simulated = false;
6276  if (!isGLES2Compliant())
6277  vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
6278  if (!isGLES2NPOTStrict())
6279  checkTextureCompleteness("drawArraysInstanced", true);
6280 
6281  m_context->drawArraysInstanced(mode, first, count, primcount);
6282 
6283  if (!isGLES2Compliant() && vertexAttrib0Simulated)
6284  restoreStatesAfterVertexAttrib0Simulation();
6285  if (!isGLES2NPOTStrict())
6286  checkTextureCompleteness("drawArraysInstanced", false);
6287  markContextChanged();
6288 }
6289 
6290 void WebGLRenderingContext::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount)
6291 {
6292  if (!primcount) {
6293  markContextChanged();
6294  return;
6295  }
6296 
6297  unsigned numElements = 0;
6298  if (!validateDrawElements("drawElementsInstanced", mode, count, type, offset, numElements, primcount))
6299  return;
6300 
6301  clearIfComposited();
6302 
6303  bool vertexAttrib0Simulated = false;
6304  if (!isGLES2Compliant()) {
6305  if (!numElements)
6306  validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
6307  vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
6308  }
6309  if (!isGLES2NPOTStrict())
6310  checkTextureCompleteness("drawElementsInstanced", true);
6311 
6312  m_context->drawElementsInstanced(mode, count, type, static_cast<GC3Dintptr>(offset), primcount);
6313 
6314  if (!isGLES2Compliant() && vertexAttrib0Simulated)
6315  restoreStatesAfterVertexAttrib0Simulation();
6316  if (!isGLES2NPOTStrict())
6317  checkTextureCompleteness("drawElementsInstanced", false);
6318  markContextChanged();
6319 }
6320 
6321 void WebGLRenderingContext::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
6322 {
6323  if (isContextLostOrPending())
6324  return;
6325 
6326  if (index >= m_maxVertexAttribs) {
6327  synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor", "index out of range");
6328  return;
6329  }
6330 
6331  m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor);
6332  m_context->vertexAttribDivisor(index, divisor);
6333 }
6334 
6335 
6336 } // namespace WebCore
6337 
6338 #endif // ENABLE(WEBGL)
178372

Source/WebCore/html/canvas/WebGLRenderingContext.h

1 /*
2  * Copyright (C) 2009, 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef WebGLRenderingContext_h
27 #define WebGLRenderingContext_h
28 
29 #include "ActiveDOMObject.h"
30 #include "CanvasRenderingContext.h"
31 #include "DrawingBuffer.h"
32 #include "GraphicsContext3D.h"
33 #include "ImageBuffer.h"
34 #include "Timer.h"
35 #include "WebGLGetInfo.h"
36 #include <memory>
37 #include <runtime/Float32Array.h>
38 #include <runtime/Int32Array.h>
39 #include <wtf/text/WTFString.h>
40 
41 namespace WebCore {
42 
43 class ANGLEInstancedArrays;
44 class EXTBlendMinMax;
45 class EXTTextureFilterAnisotropic;
46 class EXTShaderTextureLOD;
47 class EXTsRGB;
48 class EXTFragDepth;
49 class HTMLImageElement;
50 class HTMLVideoElement;
51 class ImageBuffer;
52 class ImageData;
53 class IntSize;
54 class OESStandardDerivatives;
55 class OESTextureFloat;
56 class OESTextureFloatLinear;
57 class OESTextureHalfFloat;
58 class OESTextureHalfFloatLinear;
59 class OESVertexArrayObject;
60 class OESElementIndexUint;
61 class WebGLActiveInfo;
62 class WebGLBuffer;
63 class WebGLContextGroup;
64 class WebGLContextObject;
65 class WebGLCompressedTextureATC;
66 class WebGLCompressedTexturePVRTC;
67 class WebGLCompressedTextureS3TC;
68 class WebGLContextAttributes;
69 class WebGLDebugRendererInfo;
70 class WebGLDebugShaders;
71 class WebGLDepthTexture;
72 class WebGLDrawBuffers;
73 class WebGLExtension;
74 class WebGLFramebuffer;
75 class WebGLLoseContext;
76 class WebGLObject;
77 class WebGLProgram;
78 class WebGLRenderbuffer;
79 class WebGLShader;
80 class WebGLSharedObject;
81 class WebGLShaderPrecisionFormat;
82 class WebGLTexture;
83 class WebGLUniformLocation;
84 class WebGLVertexArrayObjectOES;
85 
86 typedef int ExceptionCode;
87 
88 class WebGLRenderingContext final : public CanvasRenderingContext, public ActiveDOMObject {
89 public:
90  static std::unique_ptr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*);
91  virtual ~WebGLRenderingContext();
92 
93  virtual bool is3d() const override { return true; }
94 #if PLATFORM(WIN)
95  // FIXME: Implement accelerated 3d canvas on Windows.
96  virtual bool isAccelerated() const override { return false; }
97 #else
98  virtual bool isAccelerated() const override { return true; }
99 #endif
100 
101  int drawingBufferWidth() const;
102  int drawingBufferHeight() const;
103 
104  void activeTexture(GC3Denum texture, ExceptionCode&);
105  void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
106  void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&);
107  void bindBuffer(GC3Denum target, WebGLBuffer*, ExceptionCode&);
108  void bindFramebuffer(GC3Denum target, WebGLFramebuffer*, ExceptionCode&);
109  void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*, ExceptionCode&);
110  void bindTexture(GC3Denum target, WebGLTexture*, ExceptionCode&);
111  void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
112  void blendEquation(GC3Denum mode);
113  void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
114  void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
115  void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
116 
117  void bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode&);
118  void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode&);
119  void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode&);
120  void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode&);
121  void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode&);
122 
123  GC3Denum checkFramebufferStatus(GC3Denum target);
124  void clear(GC3Dbitfield mask);
125  void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
126  void clearDepth(GC3Dfloat);
127  void clearStencil(GC3Dint);
128  void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
129  void compileShader(WebGLShader*, ExceptionCode&);
130 
131  void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
132  GC3Dsizei height, GC3Dint border, ArrayBufferView* data);
133  void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
134  GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
135 
136  void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
137  void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
138 
139  PassRefPtr<WebGLBuffer> createBuffer();
140  PassRefPtr<WebGLFramebuffer> createFramebuffer();
141  PassRefPtr<WebGLProgram> createProgram();
142  PassRefPtr<WebGLRenderbuffer> createRenderbuffer();
143  PassRefPtr<WebGLShader> createShader(GC3Denum type, ExceptionCode&);
144  PassRefPtr<WebGLTexture> createTexture();
145 
146  void cullFace(GC3Denum mode);
147 
148  void deleteBuffer(WebGLBuffer*);
149  void deleteFramebuffer(WebGLFramebuffer*);
150  void deleteProgram(WebGLProgram*);
151  void deleteRenderbuffer(WebGLRenderbuffer*);
152  void deleteShader(WebGLShader*);
153  void deleteTexture(WebGLTexture*);
154 
155  void depthFunc(GC3Denum);
156  void depthMask(GC3Dboolean);
157  void depthRange(GC3Dfloat zNear, GC3Dfloat zFar);
158  void detachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
159  void disable(GC3Denum cap);
160  void disableVertexAttribArray(GC3Duint index, ExceptionCode&);
161  void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode&);
162  void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode&);
163 
164  void enable(GC3Denum cap);
165  void enableVertexAttribArray(GC3Duint index, ExceptionCode&);
166  void finish();
167  void flush();
168  void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*, ExceptionCode&);
169  void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level, ExceptionCode&);
170  void frontFace(GC3Denum mode);
171  void generateMipmap(GC3Denum target);
172 
173  PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index, ExceptionCode&);
174  PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index, ExceptionCode&);
175  bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader>>&, ExceptionCode&);
176  GC3Dint getAttribLocation(WebGLProgram*, const String& name);
177  WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
178  PassRefPtr<WebGLContextAttributes> getContextAttributes();
179  GC3Denum getError();
180  WebGLExtension* getExtension(const String& name);
181  WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&);
182  WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&);
183  WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname, ExceptionCode&);
184  String getProgramInfoLog(WebGLProgram*, ExceptionCode&);
185  WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
186  WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname, ExceptionCode&);
187  String getShaderInfoLog(WebGLShader*, ExceptionCode&);
188  PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode&);
189  String getShaderSource(WebGLShader*, ExceptionCode&);
190  Vector<String> getSupportedExtensions();
191  WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
192  WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*, ExceptionCode&);
193  PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&, ExceptionCode&);
194  WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode&);
195  long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
196 
197  void hint(GC3Denum target, GC3Denum mode);
198  GC3Dboolean isBuffer(WebGLBuffer*);
199  bool isContextLost() const;
200  GC3Dboolean isEnabled(GC3Denum cap);
201  GC3Dboolean isFramebuffer(WebGLFramebuffer*);
202  GC3Dboolean isProgram(WebGLProgram*);
203  GC3Dboolean isRenderbuffer(WebGLRenderbuffer*);
204  GC3Dboolean isShader(WebGLShader*);
205  GC3Dboolean isTexture(WebGLTexture*);
206 
207  void lineWidth(GC3Dfloat);
208  void linkProgram(WebGLProgram*, ExceptionCode&);
209  void pixelStorei(GC3Denum pname, GC3Dint param);
210  void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
211  void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&);
212  void releaseShaderCompiler();
213  void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
214  void sampleCoverage(GC3Dfloat value, GC3Dboolean invert);
215  void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
216  void shaderSource(WebGLShader*, const String&, ExceptionCode&);
217  void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
218  void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
219  void stencilMask(GC3Duint);
220  void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
221  void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
222  void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
223 
224  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
225  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
226  GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
227  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
228  GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
229  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
230  GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
231  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
232  GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
233 #if ENABLE(VIDEO)
234  void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
235  GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
236 #endif
237 
238  void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
239  void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
240 
241  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
242  GC3Dsizei width, GC3Dsizei height,
243  GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
244  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
245  GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
246  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
247  GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
248  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
249  GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
250 #if ENABLE(VIDEO)
251  void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
252  GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
253 #endif
254 
255  void uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode&);
256  void uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
257  void uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
258  void uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode&);
259  void uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
260  void uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
261  void uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode&);
262  void uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
263  void uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
264  void uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode&);
265  void uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
266  void uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
267  void uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode&);
268  void uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
269  void uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
270  void uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode&);
271  void uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
272  void uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
273  void uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode&);
274  void uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
275  void uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
276  void uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode&);
277  void uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
278  void uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
279  void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
280  void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
281  void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
282  void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
283  void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
284  void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
285 
286  void useProgram(WebGLProgram*, ExceptionCode&);
287  void validateProgram(WebGLProgram*, ExceptionCode&);
288 
289  void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
290  void vertexAttrib1fv(GC3Duint index, Float32Array* values);
291  void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
292  void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
293  void vertexAttrib2fv(GC3Duint index, Float32Array* values);
294  void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
295  void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
296  void vertexAttrib3fv(GC3Duint index, Float32Array* values);
297  void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
298  void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
299  void vertexAttrib4fv(GC3Duint index, Float32Array* values);
300  void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
301  void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
302  GC3Dsizei stride, long long offset, ExceptionCode&);
303 
304  void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
305 
306  // WEBKIT_lose_context support
307  enum LostContextMode {
308  // Lost context occurred at the graphics system level.
309  RealLostContext,
310 
311  // Lost context provoked by WEBKIT_lose_context.
312  SyntheticLostContext
313  };
314  void forceLostContext(LostContextMode);
315  void forceRestoreContext();
316  void loseContextImpl(LostContextMode);
317 
318  GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
319  WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
320  virtual PlatformLayer* platformLayer() const override;
321 
322  void reshape(int width, int height);
323 
324  void markLayerComposited();
325  virtual void paintRenderingResultsToCanvas() override;
326  PassRefPtr<ImageData> paintRenderingResultsToImageData();
327 
328  void removeSharedObject(WebGLSharedObject*);
329  void removeContextObject(WebGLContextObject*);
330 
331  unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; }
332 
333  // ANGLE_instanced_arrays extension functions.
334  void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
335  void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount);
336  void vertexAttribDivisor(GC3Duint index, GC3Duint divisor);
337 
338 private:
339  friend class WebGLDrawBuffers;
340  friend class WebGLFramebuffer;
341  friend class WebGLObject;
342  friend class OESVertexArrayObject;
343  friend class WebGLDebugShaders;
344  friend class WebGLCompressedTextureATC;
345  friend class WebGLCompressedTexturePVRTC;
346  friend class WebGLCompressedTextureS3TC;
347  friend class WebGLRenderingContextErrorMessageCallback;
348  friend class WebGLVertexArrayObjectOES;
349 
350  WebGLRenderingContext(HTMLCanvasElement*, GraphicsContext3D::Attributes);
351  WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes);
352  void initializeNewContext();
353  void setupFlags();
354 
355  // ActiveDOMObject
356  virtual bool hasPendingActivity() const override;
357  virtual void stop() override;
358  virtual const char* activeDOMObjectName() const override { return "WebGLRenderingContext"; }
359 
360  void addSharedObject(WebGLSharedObject*);
361  void addContextObject(WebGLContextObject*);
362  void detachAndRemoveAllObjects();
363 
364  void destroyGraphicsContext3D();
365  void markContextChanged();
366 
367  // Query whether it is built on top of compliant GLES2 implementation.
368  bool isGLES2Compliant() { return m_isGLES2Compliant; }
369  // Query if the GL implementation is NPOT strict.
370  bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; }
371  // Query if the GL implementation generates errors on out-of-bounds buffer accesses.
372  bool isErrorGeneratedOnOutOfBoundsAccesses() { return m_isErrorGeneratedOnOutOfBoundsAccesses; }
373  // Query if the GL implementation initializes textures/renderbuffers to 0.
374  bool isResourceSafe() { return m_isResourceSafe; }
375  // Query if depth_stencil buffer is supported.
376  bool isDepthStencilSupported() { return m_isDepthStencilSupported; }
377 
378  // Helper to return the size in bytes of OpenGL data types
379  // like GL_FLOAT, GL_INT, etc.
380  unsigned int sizeInBytes(GC3Denum type);
381 
382  // Basic validation of count and offset against number of elements in element array buffer
383  bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
384 
385  // Conservative but quick index validation
386  bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired);
387 
388  // Precise but slow index validation -- only done if conservative checks fail
389  bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired);
390  bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0);
391 
392  bool validateWebGLObject(const char*, WebGLObject*);
393 
394  bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
395  bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount);
396 
397  // Adds a compressed texture format.
398  void addCompressedTextureFormat(GC3Denum);
399 
400  PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, int deviceScaleFactor);
401 
402 #if ENABLE(VIDEO)
403  PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy, ExceptionCode&);
404 #endif
405 
406  RefPtr<GraphicsContext3D> m_context;
407  RefPtr<WebGLContextGroup> m_contextGroup;
408 
409  // Optional structure for rendering to a DrawingBuffer, instead of directly
410  // to the back-buffer of m_context.
411  RefPtr<DrawingBuffer> m_drawingBuffer;
412 
413  // Dispatches a context lost event once it is determined that one is needed.
414  // This is used both for synthetic and real context losses. For real ones, it's
415  // likely that there's no JavaScript on the stack, but that might be dependent
416  // on how exactly the platform discovers that the context was lost. For better
417  // portability we always defer the dispatch of the event.
418  Timer m_dispatchContextLostEventTimer;
419  bool m_restoreAllowed;
420  Timer m_restoreTimer;
421 
422  bool m_needsUpdate;
423  bool m_markedCanvasDirty;
424  HashSet<WebGLContextObject*> m_contextObjects;
425 
426  // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
427  RefPtr<WebGLBuffer> m_boundArrayBuffer;
428 
429  RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject;
430  RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject;
431  void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject)
432  {
433  if (arrayObject)
434  m_boundVertexArrayObject = arrayObject;
435  else
436  m_boundVertexArrayObject = m_defaultVertexArrayObject;
437  }
438 
439  class VertexAttribValue {
440  public:
441  VertexAttribValue()
442  {
443  initValue();
444  }
445 
446  void initValue()
447  {
448  value[0] = 0.0f;
449  value[1] = 0.0f;
450  value[2] = 0.0f;
451  value[3] = 1.0f;
452  }
453 
454  GC3Dfloat value[4];
455  };
456  Vector<VertexAttribValue> m_vertexAttribValue;
457  unsigned m_maxVertexAttribs;
458  RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
459  long m_vertexAttrib0BufferSize;
460  GC3Dfloat m_vertexAttrib0BufferValue[4];
461  bool m_forceAttrib0BufferRefill;
462  bool m_vertexAttrib0UsedBefore;
463 
464  RefPtr<WebGLProgram> m_currentProgram;
465  RefPtr<WebGLFramebuffer> m_framebufferBinding;
466  RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
467  struct TextureUnitState {
468  RefPtr<WebGLTexture> texture2DBinding;
469  RefPtr<WebGLTexture> textureCubeMapBinding;
470  };
471  Vector<TextureUnitState> m_textureUnits;
472  unsigned long m_activeTextureUnit;
473 
474  RefPtr<WebGLTexture> m_blackTexture2D;
475  RefPtr<WebGLTexture> m_blackTextureCubeMap;
476 
477  Vector<GC3Denum> m_compressedTextureFormats;
478 
479  // Fixed-size cache of reusable image buffers for video texImage2D calls.
480  class LRUImageBufferCache {
481  public:
482  LRUImageBufferCache(int capacity);
483  // The pointer returned is owned by the image buffer map.
484  ImageBuffer* imageBuffer(const IntSize& size);
485  private:
486  void bubbleToFront(int idx);
487  std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers;
488  int m_capacity;
489  };
490  LRUImageBufferCache m_generatedImageCache;
491 
492  GC3Dint m_maxTextureSize;
493  GC3Dint m_maxCubeMapTextureSize;
494  GC3Dint m_maxRenderbufferSize;
495  GC3Dint m_maxViewportDims[2];
496  GC3Dint m_maxTextureLevel;
497  GC3Dint m_maxCubeMapTextureLevel;
498 
499  GC3Dint m_maxDrawBuffers;
500  GC3Dint m_maxColorAttachments;
501  GC3Denum m_backDrawBuffer;
502  bool m_drawBuffersWebGLRequirementsChecked;
503  bool m_drawBuffersSupported;
504 
505  GC3Dint m_packAlignment;
506  GC3Dint m_unpackAlignment;
507  bool m_unpackFlipY;
508  bool m_unpackPremultiplyAlpha;
509  GC3Denum m_unpackColorspaceConversion;
510  bool m_contextLost;
511  LostContextMode m_contextLostMode;
512  GraphicsContext3D::Attributes m_attributes;
513 
514  bool m_layerCleared;
515  GC3Dfloat m_clearColor[4];
516  bool m_scissorEnabled;
517  GC3Dfloat m_clearDepth;
518  GC3Dint m_clearStencil;
519  GC3Dboolean m_colorMask[4];
520  GC3Dboolean m_depthMask;
521 
522  bool m_stencilEnabled;
523  GC3Duint m_stencilMask, m_stencilMaskBack;
524  GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
525  GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack;
526 
527  bool m_isGLES2Compliant;
528  bool m_isGLES2NPOTStrict;
529  bool m_isErrorGeneratedOnOutOfBoundsAccesses;
530  bool m_isResourceSafe;
531  bool m_isDepthStencilSupported;
532  bool m_isRobustnessEXTSupported;
533 
534  bool m_synthesizedErrorsToConsole;
535  int m_numGLErrorsToConsoleAllowed;
536 
537  // A WebGLRenderingContext can be created in a state where it appears as
538  // a valid and active context, but will not execute any important operations
539  // until its load policy is completely resolved.
540  bool m_isPendingPolicyResolution;
541  bool m_hasRequestedPolicyResolution;
542  bool isContextLostOrPending();
543 
544  // Enabled extension objects.
545  std::unique_ptr<EXTFragDepth> m_extFragDepth;
546  std::unique_ptr<EXTBlendMinMax> m_extBlendMinMax;
547  std::unique_ptr<EXTsRGB> m_extsRGB;
548  std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic;
549  std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD;
550  std::unique_ptr<OESTextureFloat> m_oesTextureFloat;
551  std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear;
552  std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat;
553  std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear;
554  std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives;
555  std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject;
556  std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint;
557  std::unique_ptr<WebGLLoseContext> m_webglLoseContext;
558  std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo;
559  std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders;
560  std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC;
561  std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC;
562  std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC;
563  std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture;
564  std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers;
565  std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays;
566 
567  // Helpers for getParameter and others
568  WebGLGetInfo getBooleanParameter(GC3Denum);
569  WebGLGetInfo getBooleanArrayParameter(GC3Denum);
570  WebGLGetInfo getFloatParameter(GC3Denum);
571  WebGLGetInfo getIntParameter(GC3Denum);
572  WebGLGetInfo getUnsignedIntParameter(GC3Denum);
573  WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum);
574  WebGLGetInfo getWebGLIntArrayParameter(GC3Denum);
575 
576  // Clear the backbuffer if it was composited since the last operation.
577  // clearMask is set to the bitfield of any clear that would happen anyway at this time
578  // and the function returns true if that clear is now unnecessary.
579  bool clearIfComposited(GC3Dbitfield clearMask = 0);
580 
581  // Helper to restore state that clearing the framebuffer may destroy.
582  void restoreStateAfterClear();
583 
584  void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
585  void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
586  void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
587  void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
588 
589  void checkTextureCompleteness(const char*, bool);
590 
591  void createFallbackBlackTextures1x1();
592 
593  // Helper function for copyTex{Sub}Image, check whether the internalformat
594  // and the color buffer format of the current bound framebuffer combination
595  // is valid.
596  bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
597  GC3Denum colorBufferFormat);
598 
599  // Helper function to get the bound framebuffer's color buffer format.
600  GC3Denum getBoundFramebufferColorFormat();
601 
602  // Helper function to get the bound framebuffer's width.
603  int getBoundFramebufferWidth();
604 
605  // Helper function to get the bound framebuffer's height.
606  int getBoundFramebufferHeight();
607 
608  // Helper function to verify limits on the length of uniform and attribute locations.
609  bool validateLocationLength(const char* functionName, const String&);
610 
611  // Helper function to check if size is non-negative.
612  // Generate GL error and return false for negative inputs; otherwise, return true.
613  bool validateSize(const char* functionName, GC3Dint x, GC3Dint y);
614 
615  // Helper function to check if all characters in the string belong to the
616  // ASCII subset as defined in GLSL ES 1.0 spec section 3.1.
617  bool validateString(const char* functionName, const String&);
618 
619  // Helper function to check target and texture bound to the target.
620  // Generate GL errors and return 0 if target is invalid or texture bound is
621  // null. Otherwise, return the texture bound to the target.
622  WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap);
623 
624  // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
625  // Generates GL error and returns false if parameters are invalid.
626  bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
627 
628  // Helper function to check input level for functions {copy}Tex{Sub}Image.
629  // Generates GL error and returns false if level is invalid.
630  bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
631 
632  enum TexFuncValidationFunctionType {
633  NotTexSubImage2D,
634  TexSubImage2D,
635  };
636 
637  enum TexFuncValidationSourceType {
638  SourceArrayBufferView,
639  SourceImageData,
640  SourceHTMLImageElement,
641  SourceHTMLCanvasElement,
642  SourceHTMLVideoElement,
643  };
644 
645  // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid.
646  // Otherwise, it would return quickly without doing other work.
647  bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
648  GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset);
649 
650  // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
651  // Generates GL error and returns false if parameters are invalid.
652  bool validateTexFuncParameters(const char* functionName,
653  TexFuncValidationFunctionType,
654  GC3Denum target, GC3Dint level,
655  GC3Denum internalformat,
656  GC3Dsizei width, GC3Dsizei height, GC3Dint border,
657  GC3Denum format, GC3Denum type);
658 
659  enum NullDisposition {
660  NullAllowed,
661  NullNotAllowed
662  };
663 
664  // Helper function to validate that the given ArrayBufferView
665  // is of the correct type and contains enough data for the texImage call.
666  // Generates GL error and returns false if parameters are invalid.
667  bool validateTexFuncData(const char* functionName, GC3Dint level,
668  GC3Dsizei width, GC3Dsizei height,
669  GC3Denum format, GC3Denum type,
670  ArrayBufferView* pixels,
671  NullDisposition);
672 
673  // Helper function to validate a given texture format is settable as in
674  // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
675  // copyTexSubImage2D.
676  // Generates GL error and returns false if the format is not settable.
677  bool validateSettableTexFormat(const char* functionName, GC3Denum format);
678 
679  // Helper function to validate compressed texture data is correct size
680  // for the given format and dimensions.
681  bool validateCompressedTexFuncData(const char* functionName,
682  GC3Dsizei width, GC3Dsizei height,
683  GC3Denum format, ArrayBufferView* pixels);
684 
685  // Helper function for validating compressed texture formats.
686  bool validateCompressedTexFormat(GC3Denum format);
687 
688  // Helper function to validate compressed texture dimensions are valid for
689  // the given format.
690  bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
691 
692  // Helper function to validate compressed texture dimensions are valid for
693  // the given format.
694  bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
695  GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
696 
697  // Helper function to validate mode for draw{Arrays/Elements}.
698  bool validateDrawMode(const char* functionName, GC3Denum);
699 
700  // Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
701  bool validateStencilSettings(const char* functionName);
702 
703  // Helper function to validate stencil func.
704  bool validateStencilFunc(const char* functionName, GC3Denum);
705 
706  // Helper function for texParameterf and texParameteri.
707  void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
708 
709  // Helper function to print GL errors to console.
710  void printGLErrorToConsole(const String&);
711  void printGLWarningToConsole(const char* function, const char* reason);
712 
713  // Helper function to print warnings to console. Currently
714  // used only to warn about use of obsolete functions.
715  void printWarningToConsole(const String&);
716 
717  // Helper function to validate input parameters for framebuffer functions.
718  // Generate GL error if parameters are illegal.
719  bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment);
720 
721  // Helper function to validate blend equation mode.
722  bool validateBlendEquation(const char* functionName, GC3Denum);
723 
724  // Helper function to validate blend func factors.
725  bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
726 
727  // Helper function to validate a GL capability.
728  bool validateCapability(const char* functionName, GC3Denum);
729 
730  // Helper function to validate input parameters for uniform functions.
731  bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod);
732  bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod);
733  bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod);
734  bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod);
735  bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod);
736 
737  // Helper function to validate parameters for bufferData.
738  // Return the current bound buffer to target, or 0 if parameters are invalid.
739  WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage);
740 
741  // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin.
742  bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&);
743 
744  // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin.
745  bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&);
746 
747 #if ENABLE(VIDEO)
748  // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin.
749  bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&);
750 #endif
751 
752  // Helper functions for vertexAttribNf{v}.
753  void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat);
754  void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize);
755  void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize);
756 
757  // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
758  // Return false if caller should return without further processing.
759  bool deleteObject(WebGLObject*);
760 
761  // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram.
762  // If the object has already been deleted, set deleted to true upon return.
763  // Return false if caller should return without further processing.
764  bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted);
765 
766  // Helpers for simulating vertexAttrib0
767  void initVertexAttrib0();
768  bool simulateVertexAttrib0(GC3Dsizei numVertex);
769  void restoreStatesAfterVertexAttrib0Simulation();
770 
771  void dispatchContextLostEvent();
772  // Helper for restoration after context lost.
773  void maybeRestoreContext();
774 
775  // Determine if we are running privileged code in the browser, for example,
776  // a Safari or Chrome extension.
777  bool allowPrivilegedExtensions() const;
778 
779  enum ConsoleDisplayPreference {
780  DisplayInConsole,
781  DontDisplayInConsole
782  };
783 
784  // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message
785  // to the JavaScript console.
786  void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole);
787 
788  String ensureNotNull(const String&) const;
789 
790  // Enable or disable stencil test based on user setting and
791  // whether the current FBO has a stencil buffer.
792  void applyStencilTest();
793 
794  // Helper for enabling or disabling a capability.
795  void enableOrDisable(GC3Denum capability, bool enable);
796 
797  // Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
798  IntSize clampedCanvasSize();
799 
800  // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0.
801  // Later, return the cached value.
802  GC3Dint getMaxDrawBuffers();
803  GC3Dint getMaxColorAttachments();
804 
805  void setBackDrawBuffer(GC3Denum);
806 
807  void restoreCurrentFramebuffer();
808  void restoreCurrentTexture2D();
809 
810  // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
811  bool supportsDrawBuffers();
812 };
813 
814 } // namespace WebCore
815 
816 #endif
178372

Source/WebCore/html/canvas/WebGLRenderingContext.idl

1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 typedef unsigned long GLenum;
27 typedef boolean GLboolean;
28 typedef unsigned long GLbitfield;
29 typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */
30 typedef short GLshort;
31 typedef long GLint;
32 typedef long GLsizei;
33 typedef long long GLintptr;
34 typedef long long GLsizeiptr;
35 typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */
36 typedef unsigned short GLushort;
37 typedef unsigned long GLuint;
38 typedef unrestricted float GLfloat;
39 typedef unrestricted float GLclampf;
40 
41 [
42  Conditional=WEBGL,
43  JSCustomMarkFunction,
44  DoNotCheckConstants,
45 ] interface WebGLRenderingContext : CanvasRenderingContext {
46 
47  /* ClearBufferMask */
48  const GLenum DEPTH_BUFFER_BIT = 0x00000100;
49  const GLenum STENCIL_BUFFER_BIT = 0x00000400;
50  const GLenum COLOR_BUFFER_BIT = 0x00004000;
51 
52  /* BeginMode */
53  const GLenum POINTS = 0x0000;
54  const GLenum LINES = 0x0001;
55  const GLenum LINE_LOOP = 0x0002;
56  const GLenum LINE_STRIP = 0x0003;
57  const GLenum TRIANGLES = 0x0004;
58  const GLenum TRIANGLE_STRIP = 0x0005;
59  const GLenum TRIANGLE_FAN = 0x0006;
60 
61  /* AlphaFunction (not supported in ES20) */
62  /* NEVER */
63  /* LESS */
64  /* EQUAL */
65  /* LEQUAL */
66  /* GREATER */
67  /* NOTEQUAL */
68  /* GEQUAL */
69  /* ALWAYS */
70 
71  /* BlendingFactorDest */
72  const GLenum ZERO = 0;
73  const GLenum ONE = 1;
74  const GLenum SRC_COLOR = 0x0300;
75  const GLenum ONE_MINUS_SRC_COLOR = 0x0301;
76  const GLenum SRC_ALPHA = 0x0302;
77  const GLenum ONE_MINUS_SRC_ALPHA = 0x0303;
78  const GLenum DST_ALPHA = 0x0304;
79  const GLenum ONE_MINUS_DST_ALPHA = 0x0305;
80 
81  /* BlendingFactorSrc */
82  /* ZERO */
83  /* ONE */
84  const GLenum DST_COLOR = 0x0306;
85  const GLenum ONE_MINUS_DST_COLOR = 0x0307;
86  const GLenum SRC_ALPHA_SATURATE = 0x0308;
87  /* SRC_ALPHA */
88  /* ONE_MINUS_SRC_ALPHA */
89  /* DST_ALPHA */
90  /* ONE_MINUS_DST_ALPHA */
91 
92  /* BlendEquationSeparate */
93  const GLenum FUNC_ADD = 0x8006;
94  const GLenum BLEND_EQUATION = 0x8009;
95  const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */
96  const GLenum BLEND_EQUATION_ALPHA = 0x883D;
97 
98  /* BlendSubtract */
99  const GLenum FUNC_SUBTRACT = 0x800A;
100  const GLenum FUNC_REVERSE_SUBTRACT = 0x800B;
101 
102  /* Separate Blend Functions */
103  const GLenum BLEND_DST_RGB = 0x80C8;
104  const GLenum BLEND_SRC_RGB = 0x80C9;
105  const GLenum BLEND_DST_ALPHA = 0x80CA;
106  const GLenum BLEND_SRC_ALPHA = 0x80CB;
107  const GLenum CONSTANT_COLOR = 0x8001;
108  const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002;
109  const GLenum CONSTANT_ALPHA = 0x8003;
110  const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004;
111  const GLenum BLEND_COLOR = 0x8005;
112 
113  /* Buffer Objects */
114  const GLenum ARRAY_BUFFER = 0x8892;
115  const GLenum ELEMENT_ARRAY_BUFFER = 0x8893;
116  const GLenum ARRAY_BUFFER_BINDING = 0x8894;
117  const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
118 
119  const GLenum STREAM_DRAW = 0x88E0;
120  const GLenum STATIC_DRAW = 0x88E4;
121  const GLenum DYNAMIC_DRAW = 0x88E8;
122 
123  const GLenum BUFFER_SIZE = 0x8764;
124  const GLenum BUFFER_USAGE = 0x8765;
125 
126  const GLenum CURRENT_VERTEX_ATTRIB = 0x8626;
127 
128  /* CullFaceMode */
129  const GLenum FRONT = 0x0404;
130  const GLenum BACK = 0x0405;
131  const GLenum FRONT_AND_BACK = 0x0408;
132 
133  /* DepthFunction */
134  /* NEVER */
135  /* LESS */
136  /* EQUAL */
137  /* LEQUAL */
138  /* GREATER */
139  /* NOTEQUAL */
140  /* GEQUAL */
141  /* ALWAYS */
142 
143  /* EnableCap */
144  const GLenum TEXTURE_2D = 0x0DE1;
145  const GLenum CULL_FACE = 0x0B44;
146  const GLenum BLEND = 0x0BE2;
147  const GLenum DITHER = 0x0BD0;
148  const GLenum STENCIL_TEST = 0x0B90;
149  const GLenum DEPTH_TEST = 0x0B71;
150  const GLenum SCISSOR_TEST = 0x0C11;
151  const GLenum POLYGON_OFFSET_FILL = 0x8037;
152  const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
153  const GLenum SAMPLE_COVERAGE = 0x80A0;
154 
155  /* ErrorCode */
156  const GLenum NO_ERROR = 0;
157  const GLenum INVALID_ENUM = 0x0500;
158  const GLenum INVALID_VALUE = 0x0501;
159  const GLenum INVALID_OPERATION = 0x0502;
160  const GLenum OUT_OF_MEMORY = 0x0505;
161 
162  /* FrontFaceDirection */
163  const GLenum CW = 0x0900;
164  const GLenum CCW = 0x0901;
165 
166  /* GetPName */
167  const GLenum LINE_WIDTH = 0x0B21;
168  const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D;
169  const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E;
170  const GLenum CULL_FACE_MODE = 0x0B45;
171  const GLenum FRONT_FACE = 0x0B46;
172  const GLenum DEPTH_RANGE = 0x0B70;
173  const GLenum DEPTH_WRITEMASK = 0x0B72;
174  const GLenum DEPTH_CLEAR_VALUE = 0x0B73;
175  const GLenum DEPTH_FUNC = 0x0B74;
176  const GLenum STENCIL_CLEAR_VALUE = 0x0B91;
177  const GLenum STENCIL_FUNC = 0x0B92;
178  const GLenum STENCIL_FAIL = 0x0B94;
179  const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95;
180  const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96;
181  const GLenum STENCIL_REF = 0x0B97;
182  const GLenum STENCIL_VALUE_MASK = 0x0B93;
183  const GLenum STENCIL_WRITEMASK = 0x0B98;
184  const GLenum STENCIL_BACK_FUNC = 0x8800;
185  const GLenum STENCIL_BACK_FAIL = 0x8801;
186  const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
187  const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
188  const GLenum STENCIL_BACK_REF = 0x8CA3;
189  const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4;
190  const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5;
191  const GLenum VIEWPORT = 0x0BA2;
192  const GLenum SCISSOR_BOX = 0x0C10;
193  /* SCISSOR_TEST */
194  const GLenum COLOR_CLEAR_VALUE = 0x0C22;
195  const GLenum COLOR_WRITEMASK = 0x0C23;
196  const GLenum UNPACK_ALIGNMENT = 0x0CF5;
197  const GLenum PACK_ALIGNMENT = 0x0D05;
198  const GLenum MAX_TEXTURE_SIZE = 0x0D33;
199  const GLenum MAX_VIEWPORT_DIMS = 0x0D3A;
200  const GLenum SUBPIXEL_BITS = 0x0D50;
201  const GLenum RED_BITS = 0x0D52;
202  const GLenum GREEN_BITS = 0x0D53;
203  const GLenum BLUE_BITS = 0x0D54;
204  const GLenum ALPHA_BITS = 0x0D55;
205  const GLenum DEPTH_BITS = 0x0D56;
206  const GLenum STENCIL_BITS = 0x0D57;
207  const GLenum POLYGON_OFFSET_UNITS = 0x2A00;
208  /* POLYGON_OFFSET_FILL */
209  const GLenum POLYGON_OFFSET_FACTOR = 0x8038;
210  const GLenum TEXTURE_BINDING_2D = 0x8069;
211  const GLenum SAMPLE_BUFFERS = 0x80A8;
212  const GLenum SAMPLES = 0x80A9;
213  const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA;
214  const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB;
215 
216  /* GetTextureParameter */
217  /* TEXTURE_MAG_FILTER */
218  /* TEXTURE_MIN_FILTER */
219  /* TEXTURE_WRAP_S */
220  /* TEXTURE_WRAP_T */
221 
222  const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3;
223 
224  /* HintMode */
225  const GLenum DONT_CARE = 0x1100;
226  const GLenum FASTEST = 0x1101;
227  const GLenum NICEST = 0x1102;
228 
229  /* HintTarget */
230  const GLenum GENERATE_MIPMAP_HINT = 0x8192;
231 
232  /* DataType */
233  const GLenum BYTE = 0x1400;
234  const GLenum UNSIGNED_BYTE = 0x1401;
235  const GLenum SHORT = 0x1402;
236  const GLenum UNSIGNED_SHORT = 0x1403;
237  const GLenum INT = 0x1404;
238  const GLenum UNSIGNED_INT = 0x1405;
239  const GLenum FLOAT = 0x1406;
240 
241  /* PixelFormat */
242  const GLenum DEPTH_COMPONENT = 0x1902;
243  const GLenum ALPHA = 0x1906;
244  const GLenum RGB = 0x1907;
245  const GLenum RGBA = 0x1908;
246  const GLenum LUMINANCE = 0x1909;
247  const GLenum LUMINANCE_ALPHA = 0x190A;
248 
249  /* PixelType */
250  /* UNSIGNED_BYTE */
251  const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033;
252  const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034;
253  const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363;
254 
255  /* Shaders */
256  const GLenum FRAGMENT_SHADER = 0x8B30;
257  const GLenum VERTEX_SHADER = 0x8B31;
258  const GLenum MAX_VERTEX_ATTRIBS = 0x8869;
259  const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
260  const GLenum MAX_VARYING_VECTORS = 0x8DFC;
261  const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
262  const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
263  const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872;
264  const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
265  const GLenum SHADER_TYPE = 0x8B4F;
266  const GLenum DELETE_STATUS = 0x8B80;
267  const GLenum LINK_STATUS = 0x8B82;
268  const GLenum VALIDATE_STATUS = 0x8B83;
269  const GLenum ATTACHED_SHADERS = 0x8B85;
270  const GLenum ACTIVE_UNIFORMS = 0x8B86;
271  const GLenum ACTIVE_ATTRIBUTES = 0x8B89;
272  const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C;
273  const GLenum CURRENT_PROGRAM = 0x8B8D;
274 
275  /* StencilFunction */
276  const GLenum NEVER = 0x0200;
277  const GLenum LESS = 0x0201;
278  const GLenum EQUAL = 0x0202;
279  const GLenum LEQUAL = 0x0203;
280  const GLenum GREATER = 0x0204;
281  const GLenum NOTEQUAL = 0x0205;
282  const GLenum GEQUAL = 0x0206;
283  const GLenum ALWAYS = 0x0207;
284 
285  /* StencilOp */
286  /* ZERO */
287  const GLenum KEEP = 0x1E00;
288  const GLenum REPLACE = 0x1E01;
289  const GLenum INCR = 0x1E02;
290  const GLenum DECR = 0x1E03;
291  const GLenum INVERT = 0x150A;
292  const GLenum INCR_WRAP = 0x8507;
293  const GLenum DECR_WRAP = 0x8508;
294 
295  /* StringName */
296  const GLenum VENDOR = 0x1F00;
297  const GLenum RENDERER = 0x1F01;
298  const GLenum VERSION = 0x1F02;
299 
300  /* TextureMagFilter */
301  const GLenum NEAREST = 0x2600;
302  const GLenum LINEAR = 0x2601;
303 
304  /* TextureMinFilter */
305  /* NEAREST */
306  /* LINEAR */
307  const GLenum NEAREST_MIPMAP_NEAREST = 0x2700;
308  const GLenum LINEAR_MIPMAP_NEAREST = 0x2701;
309  const GLenum NEAREST_MIPMAP_LINEAR = 0x2702;
310  const GLenum LINEAR_MIPMAP_LINEAR = 0x2703;
311 
312  /* TextureParameterName */
313  const GLenum TEXTURE_MAG_FILTER = 0x2800;
314  const GLenum TEXTURE_MIN_FILTER = 0x2801;
315  const GLenum TEXTURE_WRAP_S = 0x2802;
316  const GLenum TEXTURE_WRAP_T = 0x2803;
317 
318  /* TextureTarget */
319  /* TEXTURE_2D */
320  const GLenum TEXTURE = 0x1702;
321 
322  const GLenum TEXTURE_CUBE_MAP = 0x8513;
323  const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514;
324  const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
325  const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
326  const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
327  const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
328  const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
329  const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
330  const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
331 
332  /* TextureUnit */
333  const GLenum TEXTURE0 = 0x84C0;
334  const GLenum TEXTURE1 = 0x84C1;
335  const GLenum TEXTURE2 = 0x84C2;
336  const GLenum TEXTURE3 = 0x84C3;
337  const GLenum TEXTURE4 = 0x84C4;
338  const GLenum TEXTURE5 = 0x84C5;
339  const GLenum TEXTURE6 = 0x84C6;
340  const GLenum TEXTURE7 = 0x84C7;
341  const GLenum TEXTURE8 = 0x84C8;
342  const GLenum TEXTURE9 = 0x84C9;
343  const GLenum TEXTURE10 = 0x84CA;
344  const GLenum TEXTURE11 = 0x84CB;
345  const GLenum TEXTURE12 = 0x84CC;
346  const GLenum TEXTURE13 = 0x84CD;
347  const GLenum TEXTURE14 = 0x84CE;
348  const GLenum TEXTURE15 = 0x84CF;
349  const GLenum TEXTURE16 = 0x84D0;
350  const GLenum TEXTURE17 = 0x84D1;
351  const GLenum TEXTURE18 = 0x84D2;
352  const GLenum TEXTURE19 = 0x84D3;
353  const GLenum TEXTURE20 = 0x84D4;
354  const GLenum TEXTURE21 = 0x84D5;
355  const GLenum TEXTURE22 = 0x84D6;
356  const GLenum TEXTURE23 = 0x84D7;
357  const GLenum TEXTURE24 = 0x84D8;
358  const GLenum TEXTURE25 = 0x84D9;
359  const GLenum TEXTURE26 = 0x84DA;
360  const GLenum TEXTURE27 = 0x84DB;
361  const GLenum TEXTURE28 = 0x84DC;
362  const GLenum TEXTURE29 = 0x84DD;
363  const GLenum TEXTURE30 = 0x84DE;
364  const GLenum TEXTURE31 = 0x84DF;
365  const GLenum ACTIVE_TEXTURE = 0x84E0;
366 
367  /* TextureWrapMode */
368  const GLenum REPEAT = 0x2901;
369  const GLenum CLAMP_TO_EDGE = 0x812F;
370  const GLenum MIRRORED_REPEAT = 0x8370;
371 
372  /* Uniform Types */
373  const GLenum FLOAT_VEC2 = 0x8B50;
374  const GLenum FLOAT_VEC3 = 0x8B51;
375  const GLenum FLOAT_VEC4 = 0x8B52;
376  const GLenum INT_VEC2 = 0x8B53;
377  const GLenum INT_VEC3 = 0x8B54;
378  const GLenum INT_VEC4 = 0x8B55;
379  const GLenum BOOL = 0x8B56;
380  const GLenum BOOL_VEC2 = 0x8B57;
381  const GLenum BOOL_VEC3 = 0x8B58;
382  const GLenum BOOL_VEC4 = 0x8B59;
383  const GLenum FLOAT_MAT2 = 0x8B5A;
384  const GLenum FLOAT_MAT3 = 0x8B5B;
385  const GLenum FLOAT_MAT4 = 0x8B5C;
386  const GLenum SAMPLER_2D = 0x8B5E;
387  const GLenum SAMPLER_CUBE = 0x8B60;
388 
389  /* Vertex Arrays */
390  const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
391  const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
392  const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
393  const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
394  const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
395  const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
396  const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
397 
398  /* Shader Source */
399  const GLenum COMPILE_STATUS = 0x8B81;
400 
401  /* Shader Precision-Specified Types */
402  const GLenum LOW_FLOAT = 0x8DF0;
403  const GLenum MEDIUM_FLOAT = 0x8DF1;
404  const GLenum HIGH_FLOAT = 0x8DF2;
405  const GLenum LOW_INT = 0x8DF3;
406  const GLenum MEDIUM_INT = 0x8DF4;
407  const GLenum HIGH_INT = 0x8DF5;
408 
409  /* Framebuffer Object. */
410  const GLenum FRAMEBUFFER = 0x8D40;
411  const GLenum RENDERBUFFER = 0x8D41;
412 
413  const GLenum RGBA4 = 0x8056;
414  const GLenum RGB5_A1 = 0x8057;
415  const GLenum RGB565 = 0x8D62;
416  const GLenum DEPTH_COMPONENT16 = 0x81A5;
417  const GLenum STENCIL_INDEX = 0x1901;
418  const GLenum STENCIL_INDEX8 = 0x8D48;
419  const GLenum DEPTH_STENCIL = 0x84F9;
420 
421  const GLenum SRGB_EXT = 0x8C40;
422  const GLenum SRGB_ALPHA_EXT = 0x8C42;
423  const GLenum SRGB8_ALPHA8_EXT = 0x8C43;
424  const GLenum FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT = 0x8210;
425 
426  const GLenum MIN_EXT = 0x8007;
427  const GLenum MAX_EXT = 0x8008;
428 
429  const GLenum RENDERBUFFER_WIDTH = 0x8D42;
430  const GLenum RENDERBUFFER_HEIGHT = 0x8D43;
431  const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
432  const GLenum RENDERBUFFER_RED_SIZE = 0x8D50;
433  const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51;
434  const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52;
435  const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53;
436  const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54;
437  const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55;
438 
439  const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
440  const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
441  const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
442  const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
443 
444  const GLenum COLOR_ATTACHMENT0 = 0x8CE0;
445  const GLenum DEPTH_ATTACHMENT = 0x8D00;
446  const GLenum STENCIL_ATTACHMENT = 0x8D20;
447  const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A;
448 
449  const GLenum NONE = 0;
450 
451  const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5;
452  const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
453  const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
454  const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
455  const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
456 
457  const GLenum FRAMEBUFFER_BINDING = 0x8CA6;
458  const GLenum RENDERBUFFER_BINDING = 0x8CA7;
459  const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8;
460 
461  const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506;
462 
463  /* WebGL-specific enums */
464  const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240;
465  const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
466  const GLenum CONTEXT_LOST_WEBGL = 0x9242;
467  const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
468  const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
469 
470  readonly attribute GLsizei drawingBufferWidth;
471  readonly attribute GLsizei drawingBufferHeight;
472 
473  [StrictTypeChecking, RaisesException] void activeTexture(GLenum texture);
474  [StrictTypeChecking, RaisesException] void attachShader(WebGLProgram program, WebGLShader shader);
475  [StrictTypeChecking, RaisesException] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name);
476  [StrictTypeChecking, RaisesException] void bindBuffer(GLenum target, WebGLBuffer buffer);
477  [StrictTypeChecking, RaisesException] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer);
478  [StrictTypeChecking, RaisesException] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer);
479  [StrictTypeChecking, RaisesException] void bindTexture(GLenum target, WebGLTexture texture);
480  [StrictTypeChecking] void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
481  [StrictTypeChecking] void blendEquation(GLenum mode);
482  [StrictTypeChecking] void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
483  [StrictTypeChecking] void blendFunc(GLenum sfactor, GLenum dfactor);
484  [StrictTypeChecking] void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
485  [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
486  [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage);
487  [StrictTypeChecking, RaisesException] void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
488  [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data);
489  [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView? data);
490 
491  [StrictTypeChecking] GLenum checkFramebufferStatus(GLenum target);
492  [StrictTypeChecking] void clear(GLbitfield mask);
493  [StrictTypeChecking] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
494  [StrictTypeChecking] void clearDepth(GLclampf depth);
495  [StrictTypeChecking] void clearStencil(GLint s);
496  [StrictTypeChecking] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
497  [StrictTypeChecking, RaisesException] void compileShader(WebGLShader shader);
498 
499  [StrictTypeChecking] void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
500  GLsizei width, GLsizei height, GLint border, ArrayBufferView data);
501  [StrictTypeChecking] void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
502  GLsizei width, GLsizei height, GLenum format, ArrayBufferView data);
503 
504  [StrictTypeChecking] void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
505  [StrictTypeChecking] void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
506 
507  [StrictTypeChecking] WebGLBuffer createBuffer();
508  [StrictTypeChecking] WebGLFramebuffer createFramebuffer();
509  [StrictTypeChecking] WebGLProgram createProgram();
510  [StrictTypeChecking] WebGLRenderbuffer createRenderbuffer();
511  [StrictTypeChecking, RaisesException] WebGLShader createShader(GLenum type);
512  [StrictTypeChecking] WebGLTexture createTexture();
513 
514  [StrictTypeChecking] void cullFace(GLenum mode);
515 
516  [StrictTypeChecking] void deleteBuffer(WebGLBuffer buffer);
517  [StrictTypeChecking] void deleteFramebuffer(WebGLFramebuffer framebuffer);
518  [StrictTypeChecking] void deleteProgram(WebGLProgram program);
519  [StrictTypeChecking] void deleteRenderbuffer(WebGLRenderbuffer renderbuffer);
520  [StrictTypeChecking] void deleteShader(WebGLShader shader);
521  [StrictTypeChecking] void deleteTexture(WebGLTexture texture);
522 
523  [StrictTypeChecking] void depthFunc(GLenum func);
524  [StrictTypeChecking] void depthMask(GLboolean flag);
525  [StrictTypeChecking] void depthRange(GLclampf zNear, GLclampf zFar);
526  [StrictTypeChecking, RaisesException] void detachShader(WebGLProgram program, WebGLShader shader);
527  [StrictTypeChecking] void disable(GLenum cap);
528  [StrictTypeChecking, RaisesException] void disableVertexAttribArray(GLuint index);
529  [StrictTypeChecking, RaisesException] void drawArrays(GLenum mode, GLint first, GLsizei count);
530  [StrictTypeChecking, RaisesException] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset);
531 
532  [StrictTypeChecking] void enable(GLenum cap);
533  [StrictTypeChecking, RaisesException] void enableVertexAttribArray(GLuint index);
534  [StrictTypeChecking] void finish();
535  [StrictTypeChecking] void flush();
536  [StrictTypeChecking, RaisesException] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer);
537  [StrictTypeChecking, RaisesException] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level);
538  [StrictTypeChecking] void frontFace(GLenum mode);
539  [StrictTypeChecking] void generateMipmap(GLenum target);
540 
541  [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index);
542  [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index);
543 
544  [StrictTypeChecking, Custom, RaisesException] void getAttachedShaders(WebGLProgram program);
545 
546  [StrictTypeChecking] GLint getAttribLocation(WebGLProgram program, DOMString name);
547 
548  [StrictTypeChecking, Custom] any getBufferParameter(GLenum target, GLenum pname);
549 
550  [StrictTypeChecking] WebGLContextAttributes getContextAttributes();
551 
552  [StrictTypeChecking] GLenum getError();
553 
554  // object getExtension(DOMString name);
555  [StrictTypeChecking, Custom] any getExtension(DOMString name);
556 
557  [StrictTypeChecking, Custom, RaisesException] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname);
558  [StrictTypeChecking, Custom, RaisesException] any getParameter(GLenum pname);
559  [StrictTypeChecking, Custom, RaisesException] any getProgramParameter(WebGLProgram program, GLenum pname);
560  [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getProgramInfoLog(WebGLProgram program);
561  [StrictTypeChecking, Custom, RaisesException] any getRenderbufferParameter(GLenum target, GLenum pname);
562  [StrictTypeChecking, Custom, RaisesException] any getShaderParameter(WebGLShader shader, GLenum pname);
563 
564  [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderInfoLog(WebGLShader shader);
565 
566  [StrictTypeChecking, RaisesException] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
567 
568  [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderSource(WebGLShader shader);
569 
570  [StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions();
571 
572  [StrictTypeChecking, Custom, RaisesException] any getTexParameter(GLenum target, GLenum pname);
573 
574  [StrictTypeChecking, Custom, RaisesException] any getUniform(WebGLProgram program, WebGLUniformLocation location);
575 
576  [StrictTypeChecking, RaisesException] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name);
577 
578  [StrictTypeChecking, Custom, RaisesException] any getVertexAttrib(GLuint index, GLenum pname);
579 
580  [StrictTypeChecking] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
581 
582  [StrictTypeChecking] void hint(GLenum target, GLenum mode);
583  [StrictTypeChecking] GLboolean isBuffer(WebGLBuffer buffer);
584  [StrictTypeChecking] GLboolean isContextLost();
585  [StrictTypeChecking] GLboolean isEnabled(GLenum cap);
586  [StrictTypeChecking] GLboolean isFramebuffer(WebGLFramebuffer framebuffer);
587  [StrictTypeChecking] GLboolean isProgram(WebGLProgram program);
588  [StrictTypeChecking] GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer);
589  [StrictTypeChecking] GLboolean isShader(WebGLShader shader);
590  [StrictTypeChecking] GLboolean isTexture(WebGLTexture texture);
591  [StrictTypeChecking] void lineWidth(GLfloat width);
592  [StrictTypeChecking, RaisesException] void linkProgram(WebGLProgram program);
593  [StrictTypeChecking] void pixelStorei(GLenum pname, GLint param);
594  [StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units);
595 
596  [StrictTypeChecking, RaisesException] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels);
597 
598  [StrictTypeChecking] void releaseShaderCompiler();
599  [StrictTypeChecking] void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
600  [StrictTypeChecking] void sampleCoverage(GLclampf value, GLboolean invert);
601  [StrictTypeChecking] void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
602  [StrictTypeChecking, RaisesException] void shaderSource(WebGLShader shader, DOMString string);
603  [StrictTypeChecking] void stencilFunc(GLenum func, GLint ref, GLuint mask);
604  [StrictTypeChecking] void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
605  [StrictTypeChecking] void stencilMask(GLuint mask);
606  [StrictTypeChecking] void stencilMaskSeparate(GLenum face, GLuint mask);
607  [StrictTypeChecking] void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
608  [StrictTypeChecking] void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
609 
610  [StrictTypeChecking] void texParameterf(GLenum target, GLenum pname, GLfloat param);
611  [StrictTypeChecking] void texParameteri(GLenum target, GLenum pname, GLint param);
612 
613  // Supported forms:
614  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
615  GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
616  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
617  GLenum format, GLenum type, ImageData? pixels);
618  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
619  GLenum format, GLenum type, HTMLImageElement? image);
620  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
621  GLenum format, GLenum type, HTMLCanvasElement? canvas);
622 #if defined(ENABLE_VIDEO) && ENABLE_VIDEO
623  [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
624  GLenum format, GLenum type, HTMLVideoElement? video);
625 #endif
626 
627  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
628  GLsizei width, GLsizei height,
629  GLenum format, GLenum type, ArrayBufferView? pixels);
630  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
631  GLenum format, GLenum type, ImageData? pixels);
632  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
633  GLenum format, GLenum type, HTMLImageElement? image);
634  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
635  GLenum format, GLenum type, HTMLCanvasElement? canvas);
636 #if defined(ENABLE_VIDEO) && ENABLE_VIDEO
637  [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
638  GLenum format, GLenum type, HTMLVideoElement? video);
639 #endif
640 
641  [StrictTypeChecking, RaisesException] void uniform1f(WebGLUniformLocation location, GLfloat x);
642  [StrictTypeChecking, Custom, RaisesException] void uniform1fv(WebGLUniformLocation location, Float32Array v);
643  [StrictTypeChecking, RaisesException] void uniform1i(WebGLUniformLocation location, GLint x);
644  [StrictTypeChecking, Custom, RaisesException] void uniform1iv(WebGLUniformLocation location, Int32Array v);
645  [StrictTypeChecking, RaisesException] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y);
646  [StrictTypeChecking, Custom, RaisesException] void uniform2fv(WebGLUniformLocation location, Float32Array v);
647  [StrictTypeChecking, RaisesException] void uniform2i(WebGLUniformLocation location, GLint x, GLint y);
648  [StrictTypeChecking, Custom, RaisesException] void uniform2iv(WebGLUniformLocation location, Int32Array v);
649  [StrictTypeChecking, RaisesException] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z);
650  [StrictTypeChecking, Custom, RaisesException] void uniform3fv(WebGLUniformLocation location, Float32Array v);
651  [StrictTypeChecking, RaisesException] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z);
652  [StrictTypeChecking, Custom, RaisesException] void uniform3iv(WebGLUniformLocation location, Int32Array v);
653  [StrictTypeChecking, RaisesException] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
654  [StrictTypeChecking, Custom, RaisesException] void uniform4fv(WebGLUniformLocation location, Float32Array v);
655  [StrictTypeChecking, RaisesException] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w);
656  [StrictTypeChecking, Custom, RaisesException] void uniform4iv(WebGLUniformLocation location, Int32Array v);
657 
658  [StrictTypeChecking, Custom, RaisesException] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
659  [StrictTypeChecking, Custom, RaisesException] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
660  [StrictTypeChecking, Custom, RaisesException] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
661 
662  [StrictTypeChecking, RaisesException] void useProgram(WebGLProgram program);
663  [StrictTypeChecking, RaisesException] void validateProgram(WebGLProgram program);
664 
665  [StrictTypeChecking] void vertexAttrib1f(GLuint indx, GLfloat x);
666  [StrictTypeChecking, Custom] void vertexAttrib1fv(GLuint indx, Float32Array values);
667  [StrictTypeChecking] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
668  [StrictTypeChecking, Custom] void vertexAttrib2fv(GLuint indx, Float32Array values);
669  [StrictTypeChecking] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
670  [StrictTypeChecking, Custom] void vertexAttrib3fv(GLuint indx, Float32Array values);
671  [StrictTypeChecking] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
672  [StrictTypeChecking, Custom] void vertexAttrib4fv(GLuint indx, Float32Array values);
673  [StrictTypeChecking, RaisesException] void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized,
674  GLsizei stride, GLintptr offset);
675 
676  [StrictTypeChecking] void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
677 };
178372

Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEBGL)
 29#include "WebGLRenderingContextBase.h"
 30
 31#include "ANGLEInstancedArrays.h"
 32#include "CachedImage.h"
 33#include "DOMWindow.h"
 34#include "Document.h"
 35#include "EXTBlendMinMax.h"
 36#include "EXTFragDepth.h"
 37#include "EXTShaderTextureLOD.h"
 38#include "EXTTextureFilterAnisotropic.h"
 39#include "EXTsRGB.h"
 40#include "ExceptionCode.h"
 41#include "Extensions3D.h"
 42#include "Frame.h"
 43#include "FrameLoader.h"
 44#include "FrameLoaderClient.h"
 45#include "FrameView.h"
 46#include "GraphicsContext.h"
 47#include "HTMLCanvasElement.h"
 48#include "HTMLImageElement.h"
 49#include "HTMLVideoElement.h"
 50#include "ImageBuffer.h"
 51#include "ImageData.h"
 52#include "IntSize.h"
 53#include "Logging.h"
 54#include "MainFrame.h"
 55#include "NotImplemented.h"
 56#include "OESElementIndexUint.h"
 57#include "OESStandardDerivatives.h"
 58#include "OESTextureFloat.h"
 59#include "OESTextureFloatLinear.h"
 60#include "OESTextureHalfFloat.h"
 61#include "OESTextureHalfFloatLinear.h"
 62#include "OESVertexArrayObject.h"
 63#include "Page.h"
 64#include "RenderBox.h"
 65#include "Settings.h"
 66#include "WebGL1RenderingContext.h"
 67#include "WebGL2RenderingContext.h"
 68#include "WebGLActiveInfo.h"
 69#include "WebGLBuffer.h"
 70#include "WebGLCompressedTextureATC.h"
 71#include "WebGLCompressedTexturePVRTC.h"
 72#include "WebGLCompressedTextureS3TC.h"
 73#include "WebGLContextAttributes.h"
 74#include "WebGLContextEvent.h"
 75#include "WebGLContextGroup.h"
 76#include "WebGLDebugRendererInfo.h"
 77#include "WebGLDebugShaders.h"
 78#include "WebGLDepthTexture.h"
 79#include "WebGLDrawBuffers.h"
 80#include "WebGLFramebuffer.h"
 81#include "WebGLLoseContext.h"
 82#include "WebGLProgram.h"
 83#include "WebGLRenderbuffer.h"
 84#include "WebGLShader.h"
 85#include "WebGLShaderPrecisionFormat.h"
 86#include "WebGLTexture.h"
 87#include "WebGLUniformLocation.h"
 88
 89#include <runtime/JSCInlines.h>
 90#include <runtime/TypedArrayInlines.h>
 91#include <runtime/Uint32Array.h>
 92#include <wtf/StdLibExtras.h>
 93#include <wtf/text/CString.h>
 94#include <wtf/text/StringBuilder.h>
 95
 96namespace WebCore {
 97
 98const double secondsBetweenRestoreAttempts = 1.0;
 99const int maxGLErrorsAllowedToConsole = 256;
 100
 101namespace {
 102
 103class ScopedDrawingBufferBinder {
 104public:
 105 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
 106 : m_drawingBuffer(drawingBuffer)
 107 , m_framebufferBinding(framebufferBinding)
 108 {
 109 // Commit DrawingBuffer if needed (e.g., for multisampling)
 110 if (!m_framebufferBinding && m_drawingBuffer)
 111 m_drawingBuffer->commit();
 112 }
 113
 114 ~ScopedDrawingBufferBinder()
 115 {
 116 // Restore DrawingBuffer if needed
 117 if (!m_framebufferBinding && m_drawingBuffer)
 118 m_drawingBuffer->bind();
 119 }
 120
 121private:
 122 DrawingBuffer* m_drawingBuffer;
 123 WebGLFramebuffer* m_framebufferBinding;
 124};
 125
 126Platform3DObject objectOrZero(WebGLObject* object)
 127{
 128 return object ? object->object() : 0;
 129}
 130
 131void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
 132{
 133 ASSERT(clippedStart && clippedRange);
 134 if (start < 0) {
 135 range += start;
 136 start = 0;
 137 }
 138 GC3Dint end = start + range;
 139 if (end > sourceRange)
 140 range -= end - sourceRange;
 141 *clippedStart = start;
 142 *clippedRange = range;
 143}
 144
 145// Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
 146bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
 147 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
 148 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
 149{
 150 ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
 151 clip1D(x, width, sourceWidth, clippedX, clippedWidth);
 152 clip1D(y, height, sourceHeight, clippedY, clippedHeight);
 153 return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
 154}
 155
 156GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
 157{
 158 if (value < min)
 159 value = min;
 160 if (value > max)
 161 value = max;
 162 return value;
 163}
 164
 165// Return true if a character belongs to the ASCII subset as defined in
 166// GLSL ES 1.0 spec section 3.1.
 167bool validateCharacter(unsigned char c)
 168{
 169 // Printing characters are valid except " $ ` @ \ ' DEL.
 170 if (c >= 32 && c <= 126
 171 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
 172 return true;
 173 // Horizontal tab, line feed, vertical tab, form feed, carriage return
 174 // are also valid.
 175 if (c >= 9 && c <= 13)
 176 return true;
 177 return false;
 178}
 179
 180bool isPrefixReserved(const String& name)
 181{
 182 if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_"))
 183 return true;
 184 return false;
 185}
 186
 187// Strips comments from shader text. This allows non-ASCII characters
 188// to be used in comments without potentially breaking OpenGL
 189// implementations not expecting characters outside the GLSL ES set.
 190class StripComments {
 191public:
 192 StripComments(const String& str)
 193 : m_parseState(BeginningOfLine)
 194 , m_sourceString(str)
 195 , m_length(str.length())
 196 , m_position(0)
 197 {
 198 parse();
 199 }
 200
 201 String result()
 202 {
 203 return m_builder.toString();
 204 }
 205
 206private:
 207 bool hasMoreCharacters() const
 208 {
 209 return (m_position < m_length);
 210 }
 211
 212 void parse()
 213 {
 214 while (hasMoreCharacters()) {
 215 process(current());
 216 // process() might advance the position.
 217 if (hasMoreCharacters())
 218 advance();
 219 }
 220 }
 221
 222 void process(UChar);
 223
 224 bool peek(UChar& character) const
 225 {
 226 if (m_position + 1 >= m_length)
 227 return false;
 228 character = m_sourceString[m_position + 1];
 229 return true;
 230 }
 231
 232 UChar current() const
 233 {
 234 ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length);
 235 return m_sourceString[m_position];
 236 }
 237
 238 void advance()
 239 {
 240 ++m_position;
 241 }
 242
 243 bool isNewline(UChar character) const
 244 {
 245 // Don't attempt to canonicalize newline related characters.
 246 return (character == '\n' || character == '\r');
 247 }
 248
 249 void emit(UChar character)
 250 {
 251 m_builder.append(character);
 252 }
 253
 254 enum ParseState {
 255 // Have not seen an ASCII non-whitespace character yet on
 256 // this line. Possible that we might see a preprocessor
 257 // directive.
 258 BeginningOfLine,
 259
 260 // Have seen at least one ASCII non-whitespace character
 261 // on this line.
 262 MiddleOfLine,
 263
 264 // Handling a preprocessor directive. Passes through all
 265 // characters up to the end of the line. Disables comment
 266 // processing.
 267 InPreprocessorDirective,
 268
 269 // Handling a single-line comment. The comment text is
 270 // replaced with a single space.
 271 InSingleLineComment,
 272
 273 // Handling a multi-line comment. Newlines are passed
 274 // through to preserve line numbers.
 275 InMultiLineComment
 276 };
 277
 278 ParseState m_parseState;
 279 String m_sourceString;
 280 unsigned m_length;
 281 unsigned m_position;
 282 StringBuilder m_builder;
 283};
 284
 285void StripComments::process(UChar c)
 286{
 287 if (isNewline(c)) {
 288 // No matter what state we are in, pass through newlines
 289 // so we preserve line numbers.
 290 emit(c);
 291
 292 if (m_parseState != InMultiLineComment)
 293 m_parseState = BeginningOfLine;
 294
 295 return;
 296 }
 297
 298 UChar temp = 0;
 299 switch (m_parseState) {
 300 case BeginningOfLine:
 301 if (WTF::isASCIISpace(c)) {
 302 emit(c);
 303 break;
 304 }
 305
 306 if (c == '#') {
 307 m_parseState = InPreprocessorDirective;
 308 emit(c);
 309 break;
 310 }
 311
 312 // Transition to normal state and re-handle character.
 313 m_parseState = MiddleOfLine;
 314 process(c);
 315 break;
 316
 317 case MiddleOfLine:
 318 if (c == '/' && peek(temp)) {
 319 if (temp == '/') {
 320 m_parseState = InSingleLineComment;
 321 emit(' ');
 322 advance();
 323 break;
 324 }
 325
 326 if (temp == '*') {
 327 m_parseState = InMultiLineComment;
 328 // Emit the comment start in case the user has
 329 // an unclosed comment and we want to later
 330 // signal an error.
 331 emit('/');
 332 emit('*');
 333 advance();
 334 break;
 335 }
 336 }
 337
 338 emit(c);
 339 break;
 340
 341 case InPreprocessorDirective:
 342 // No matter what the character is, just pass it
 343 // through. Do not parse comments in this state. This
 344 // might not be the right thing to do long term, but it
 345 // should handle the #error preprocessor directive.
 346 emit(c);
 347 break;
 348
 349 case InSingleLineComment:
 350 // The newline code at the top of this function takes care
 351 // of resetting our state when we get out of the
 352 // single-line comment. Swallow all other characters.
 353 break;
 354
 355 case InMultiLineComment:
 356 if (c == '*' && peek(temp) && temp == '/') {
 357 emit('*');
 358 emit('/');
 359 m_parseState = MiddleOfLine;
 360 advance();
 361 break;
 362 }
 363
 364 // Swallow all other characters. Unclear whether we may
 365 // want or need to just emit a space per character to try
 366 // to preserve column numbers for debugging purposes.
 367 break;
 368 }
 369}
 370} // namespace anonymous
 371
 372class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
 373 WTF_MAKE_FAST_ALLOCATED;
 374public:
 375 explicit WebGLRenderingContextLostCallback(WebGLRenderingContextBase* cb)
 376 : m_context(cb) { }
 377
 378 virtual void onContextLost() override
 379 {
 380 m_context->forceLostContext(WebGLRenderingContextBase::RealLostContext);
 381 }
 382 virtual ~WebGLRenderingContextLostCallback() { }
 383private:
 384 WebGLRenderingContextBase* m_context;
 385};
 386
 387class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback {
 388 WTF_MAKE_FAST_ALLOCATED;
 389public:
 390 explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContextBase* cb)
 391 : m_context(cb) { }
 392
 393 virtual void onErrorMessage(const String& message, GC3Dint) override
 394 {
 395 if (m_context->m_synthesizedErrorsToConsole)
 396 m_context->printGLErrorToConsole(message);
 397 }
 398 virtual ~WebGLRenderingContextErrorMessageCallback() { }
 399private:
 400 WebGLRenderingContextBase* m_context;
 401};
 402
 403std::unique_ptr<WebGLRenderingContextBase> WebGLRenderingContextBase::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs, const String& type)
 404{
 405 Document& document = canvas->document();
 406 Frame* frame = document.frame();
 407 if (!frame)
 408 return nullptr;
 409
 410 // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in
 411 // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension.
 412 if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) {
 413 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context."));
 414 return nullptr;
 415 }
 416
 417 bool isPendingPolicyResolution = false;
 418 Document& topDocument = document.topDocument();
 419 Page* page = topDocument.page();
 420 if (page && !topDocument.url().isLocalFile()) {
 421 WebGLLoadPolicy policy = page->mainFrame().loader().client().webGLPolicyForURL(topDocument.url());
 422
 423 if (policy == WebGLBlockCreation) {
 424 LOG(WebGL, "The policy for this URL (%s) is to block WebGL.", topDocument.url().host().utf8().data());
 425 return nullptr;
 426 }
 427
 428 if (policy == WebGLPendingCreation) {
 429 LOG(WebGL, "WebGL policy is pending. May need to be resolved later.");
 430 isPendingPolicyResolution = true;
 431 }
 432 }
 433
 434 GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
 435
 436 if (attributes.antialias) {
 437 if (!frame->settings().openGLMultisamplingEnabled())
 438 attributes.antialias = false;
 439 }
 440
 441 attributes.noExtensions = true;
 442 attributes.shareResources = false;
 443 attributes.preferDiscreteGPU = true;
 444
 445 if (frame->settings().forceSoftwareWebGLRendering())
 446 attributes.forceSoftwareRenderer = true;
 447
 448 if (page)
 449 attributes.devicePixelRatio = page->deviceScaleFactor();
 450
 451 if (isPendingPolicyResolution) {
 452 LOG(WebGL, "Create a WebGL context that looks real, but will require a policy resolution if used.");
 453 std::unique_ptr<WebGLRenderingContextBase> renderingContext = nil;
 454 if (type == "experimental-webgl2")
 455 renderingContext = std::unique_ptr<WebGL2RenderingContext>(new WebGL2RenderingContext(canvas, attributes));
 456 else
 457 renderingContext = std::unique_ptr<WebGL1RenderingContext>(new WebGL1RenderingContext(canvas, attributes));
 458 }
 459
 460 HostWindow* hostWindow = document.view()->root()->hostWindow();
 461 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
 462
 463 if (!context || !context->makeContextCurrent()) {
 464 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
 465 return nullptr;
 466 }
 467
 468 Extensions3D* extensions = context->getExtensions();
 469 if (extensions->supports("GL_EXT_debug_marker"))
 470 extensions->pushGroupMarkerEXT("WebGLRenderingContext");
 471
 472 std::unique_ptr<WebGLRenderingContextBase> renderingContext = nil;
 473 if (type == "experimental-webgl2")
 474 renderingContext = std::unique_ptr<WebGL2RenderingContext>(new WebGL2RenderingContext(canvas, context, attributes));
 475 else
 476 renderingContext = std::unique_ptr<WebGL1RenderingContext>(new WebGL1RenderingContext(canvas, context, attributes));
 477 renderingContext->suspendIfNeeded();
 478
 479 return renderingContext;
 480}
 481
 482WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
 483 : CanvasRenderingContext(passedCanvas)
 484 , ActiveDOMObject(&passedCanvas->document())
 485 , m_context(0)
 486 , m_drawingBuffer(0)
 487 , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContextBase::dispatchContextLostEvent)
 488 , m_restoreAllowed(false)
 489 , m_restoreTimer(*this, &WebGLRenderingContextBase::maybeRestoreContext)
 490 , m_generatedImageCache(0)
 491 , m_contextLost(false)
 492 , m_contextLostMode(SyntheticLostContext)
 493 , m_attributes(attributes)
 494 , m_synthesizedErrorsToConsole(true)
 495 , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
 496 , m_isPendingPolicyResolution(true)
 497 , m_hasRequestedPolicyResolution(false)
 498{
 499}
 500
 501WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,GraphicsContext3D::Attributes attributes)
 502 : CanvasRenderingContext(passedCanvas)
 503 , ActiveDOMObject(&passedCanvas->document())
 504 , m_context(context)
 505 , m_drawingBuffer(0)
 506 , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContextBase::dispatchContextLostEvent)
 507 , m_restoreAllowed(false)
 508 , m_restoreTimer(*this, &WebGLRenderingContextBase::maybeRestoreContext)
 509 , m_generatedImageCache(4)
 510 , m_contextLost(false)
 511 , m_contextLostMode(SyntheticLostContext)
 512 , m_attributes(attributes)
 513 , m_synthesizedErrorsToConsole(true)
 514 , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
 515 , m_isPendingPolicyResolution(false)
 516 , m_hasRequestedPolicyResolution(false)
 517{
 518 ASSERT(m_context);
 519 m_contextGroup = WebGLContextGroup::create();
 520 m_contextGroup->addContext(this);
 521
 522 m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
 523 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
 524
 525 if (m_drawingBuffer)
 526 m_drawingBuffer->bind();
 527
 528 setupFlags();
 529 initializeNewContext();
 530}
 531
 532void WebGLRenderingContextBase::initializeNewContext()
 533{
 534 ASSERT(!m_contextLost);
 535 m_needsUpdate = true;
 536 m_markedCanvasDirty = false;
 537 m_activeTextureUnit = 0;
 538 m_packAlignment = 4;
 539 m_unpackAlignment = 4;
 540 m_unpackFlipY = false;
 541 m_unpackPremultiplyAlpha = false;
 542 m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
 543 m_boundArrayBuffer = 0;
 544 m_currentProgram = 0;
 545 m_framebufferBinding = 0;
 546 m_renderbufferBinding = 0;
 547 m_depthMask = true;
 548 m_stencilEnabled = false;
 549 m_stencilMask = 0xFFFFFFFF;
 550 m_stencilMaskBack = 0xFFFFFFFF;
 551 m_stencilFuncRef = 0;
 552 m_stencilFuncRefBack = 0;
 553 m_stencilFuncMask = 0xFFFFFFFF;
 554 m_stencilFuncMaskBack = 0xFFFFFFFF;
 555 m_layerCleared = false;
 556 m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
 557
 558 m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
 559 m_scissorEnabled = false;
 560 m_clearDepth = 1;
 561 m_clearStencil = 0;
 562 m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
 563
 564 GC3Dint numCombinedTextureImageUnits = 0;
 565 m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
 566 m_textureUnits.clear();
 567 m_textureUnits.resize(numCombinedTextureImageUnits);
 568
 569 GC3Dint numVertexAttribs = 0;
 570 m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
 571 m_maxVertexAttribs = numVertexAttribs;
 572
 573 m_maxTextureSize = 0;
 574 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
 575 m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
 576 m_maxCubeMapTextureSize = 0;
 577 m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
 578 m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
 579 m_maxRenderbufferSize = 0;
 580 m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
 581
 582 // These two values from EXT_draw_buffers are lazily queried.
 583 m_maxDrawBuffers = 0;
 584 m_maxColorAttachments = 0;
 585
 586 m_backDrawBuffer = GraphicsContext3D::BACK;
 587 m_drawBuffersWebGLRequirementsChecked = false;
 588 m_drawBuffersSupported = false;
 589
 590 m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
 591 addContextObject(m_defaultVertexArrayObject.get());
 592 m_boundVertexArrayObject = m_defaultVertexArrayObject;
 593
 594 m_vertexAttribValue.resize(m_maxVertexAttribs);
 595
 596 if (!isGLES2NPOTStrict())
 597 createFallbackBlackTextures1x1();
 598 if (!isGLES2Compliant())
 599 initVertexAttrib0();
 600
 601 IntSize canvasSize = clampedCanvasSize();
 602 if (m_drawingBuffer)
 603 m_drawingBuffer->reset(canvasSize);
 604
 605 m_context->reshape(canvasSize.width(), canvasSize.height());
 606 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
 607 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
 608
 609 m_context->setContextLostCallback(std::make_unique<WebGLRenderingContextLostCallback>(this));
 610 m_context->setErrorMessageCallback(std::make_unique<WebGLRenderingContextErrorMessageCallback>(this));
 611}
 612
 613void WebGLRenderingContextBase::setupFlags()
 614{
 615 ASSERT(m_context);
 616
 617 if (Page* page = canvas()->document().page())
 618 m_synthesizedErrorsToConsole = page->settings().webGLErrorsToConsoleEnabled();
 619
 620 m_isGLES2Compliant = m_context->isGLES2Compliant();
 621 m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
 622 m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
 623 if (m_isGLES2Compliant) {
 624 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
 625 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
 626 } else {
 627 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
 628 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
 629 }
 630 m_isRobustnessEXTSupported = m_context->getExtensions()->isEnabled("GL_EXT_robustness");
 631}
 632
 633bool WebGLRenderingContextBase::allowPrivilegedExtensions() const
 634{
 635 if (Page* page = canvas()->document().page())
 636 return page->settings().privilegedWebGLExtensionsEnabled();
 637 return false;
 638}
 639
 640void WebGLRenderingContextBase::addCompressedTextureFormat(GC3Denum format)
 641{
 642 if (!m_compressedTextureFormats.contains(format))
 643 m_compressedTextureFormats.append(format);
 644}
 645
 646WebGLRenderingContextBase::~WebGLRenderingContextBase()
 647{
 648 // Remove all references to WebGLObjects so if they are the last reference
 649 // they will be freed before the last context is removed from the context group.
 650 m_boundArrayBuffer = nullptr;
 651 m_defaultVertexArrayObject = nullptr;
 652 m_boundVertexArrayObject = nullptr;
 653 m_vertexAttrib0Buffer = nullptr;
 654 m_currentProgram = nullptr;
 655 m_framebufferBinding = nullptr;
 656 m_renderbufferBinding = nullptr;
 657
 658 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
 659 m_textureUnits[i].texture2DBinding = nullptr;
 660 m_textureUnits[i].textureCubeMapBinding = nullptr;
 661 }
 662
 663 m_blackTexture2D = nullptr;
 664 m_blackTextureCubeMap = nullptr;
 665
 666 if (!m_isPendingPolicyResolution) {
 667 detachAndRemoveAllObjects();
 668 destroyGraphicsContext3D();
 669 m_contextGroup->removeContext(this);
 670 }
 671}
 672
 673void WebGLRenderingContextBase::destroyGraphicsContext3D()
 674{
 675 if (m_isPendingPolicyResolution)
 676 return;
 677
 678 // The drawing buffer holds a context reference. It must also be destroyed
 679 // in order for the context to be released.
 680 if (m_drawingBuffer)
 681 m_drawingBuffer.clear();
 682
 683 if (m_context) {
 684 m_context->setContextLostCallback(nullptr);
 685 m_context->setErrorMessageCallback(nullptr);
 686 m_context.clear();
 687 }
 688}
 689
 690void WebGLRenderingContextBase::markContextChanged()
 691{
 692 if (m_framebufferBinding)
 693 return;
 694
 695 m_context->markContextChanged();
 696
 697 if (m_drawingBuffer)
 698 m_drawingBuffer->markContentsChanged();
 699
 700 m_layerCleared = false;
 701 RenderBox* renderBox = canvas()->renderBox();
 702 if (isAccelerated() && renderBox && renderBox->hasAcceleratedCompositing()) {
 703 m_markedCanvasDirty = true;
 704 canvas()->clearCopiedImage();
 705 renderBox->contentChanged(CanvasChanged);
 706 } else {
 707 if (!m_markedCanvasDirty) {
 708 m_markedCanvasDirty = true;
 709 canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
 710 }
 711 }
 712}
 713
 714bool WebGLRenderingContextBase::clearIfComposited(GC3Dbitfield mask)
 715{
 716 if (isContextLostOrPending())
 717 return false;
 718
 719 if (!m_context->layerComposited() || m_layerCleared
 720 || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
 721 return false;
 722
 723 RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
 724
 725 // Determine if it's possible to combine the clear the user asked for and this clear.
 726 bool combinedClear = mask && !m_scissorEnabled;
 727
 728 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
 729 if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT)) {
 730 m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
 731 m_colorMask[1] ? m_clearColor[1] : 0,
 732 m_colorMask[2] ? m_clearColor[2] : 0,
 733 m_colorMask[3] ? m_clearColor[3] : 0);
 734 } else
 735 m_context->clearColor(0, 0, 0, 0);
 736 m_context->colorMask(true, true, true, true);
 737 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
 738 if (contextAttributes->depth()) {
 739 if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
 740 m_context->clearDepth(1.0f);
 741 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
 742 m_context->depthMask(true);
 743 }
 744 if (contextAttributes->stencil()) {
 745 if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
 746 m_context->clearStencil(m_clearStencil & m_stencilMask);
 747 else
 748 m_context->clearStencil(0);
 749 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
 750 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
 751 }
 752 if (m_drawingBuffer)
 753 m_drawingBuffer->clearFramebuffers(clearMask);
 754 else {
 755 if (m_framebufferBinding)
 756 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
 757 m_context->clear(clearMask);
 758 }
 759
 760 restoreStateAfterClear();
 761 if (m_framebufferBinding)
 762 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 763 m_layerCleared = true;
 764
 765 return combinedClear;
 766}
 767
 768void WebGLRenderingContextBase::restoreStateAfterClear()
 769{
 770 // Restore the state that the context set.
 771 if (m_scissorEnabled)
 772 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
 773 m_context->clearColor(m_clearColor[0], m_clearColor[1],
 774 m_clearColor[2], m_clearColor[3]);
 775 m_context->colorMask(m_colorMask[0], m_colorMask[1],
 776 m_colorMask[2], m_colorMask[3]);
 777 m_context->clearDepth(m_clearDepth);
 778 m_context->clearStencil(m_clearStencil);
 779 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
 780 m_context->depthMask(m_depthMask);
 781}
 782
 783void WebGLRenderingContextBase::markLayerComposited()
 784{
 785 if (isContextLostOrPending())
 786 return;
 787 m_context->markLayerComposited();
 788}
 789
 790void WebGLRenderingContextBase::paintRenderingResultsToCanvas()
 791{
 792 if (isContextLostOrPending())
 793 return;
 794
 795 if (canvas()->document().printing())
 796 canvas()->clearPresentationCopy();
 797
 798 // Until the canvas is written to by the application, the clear that
 799 // happened after it was composited should be ignored by the compositor.
 800 if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
 801 m_context->paintCompositedResultsToCanvas(canvas()->buffer());
 802
 803 canvas()->makePresentationCopy();
 804 } else
 805 canvas()->clearPresentationCopy();
 806 clearIfComposited();
 807
 808 if (!m_markedCanvasDirty && !m_layerCleared)
 809 return;
 810
 811 canvas()->clearCopiedImage();
 812 m_markedCanvasDirty = false;
 813
 814 if (m_drawingBuffer)
 815 m_drawingBuffer->commit();
 816 m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get());
 817
 818 if (m_drawingBuffer) {
 819 if (m_framebufferBinding)
 820 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 821 else
 822 m_drawingBuffer->bind();
 823 }
 824}
 825
 826PassRefPtr<ImageData> WebGLRenderingContextBase::paintRenderingResultsToImageData()
 827{
 828 if (isContextLostOrPending())
 829 return nullptr;
 830 clearIfComposited();
 831 if (m_drawingBuffer)
 832 m_drawingBuffer->commit();
 833 RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
 834
 835 if (m_drawingBuffer) {
 836 if (m_framebufferBinding)
 837 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 838 else
 839 m_drawingBuffer->bind();
 840 }
 841
 842 return imageData;
 843}
 844
 845void WebGLRenderingContextBase::reshape(int width, int height)
 846{
 847 if (isContextLostOrPending())
 848 return;
 849
 850 // This is an approximation because at WebGLRenderingContext level we don't
 851 // know if the underlying FBO uses textures or renderbuffers.
 852 GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
 853 // Limit drawing buffer size to 4k to avoid memory exhaustion.
 854 const int sizeUpperLimit = 4096;
 855 maxSize = std::min(maxSize, sizeUpperLimit);
 856 GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
 857 GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
 858 width = clamp(width, 1, maxWidth);
 859 height = clamp(height, 1, maxHeight);
 860
 861 if (m_needsUpdate) {
 862 RenderBox* renderBox = canvas()->renderBox();
 863 if (renderBox && renderBox->hasAcceleratedCompositing())
 864 renderBox->contentChanged(CanvasChanged);
 865 m_needsUpdate = false;
 866 }
 867
 868 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
 869 // clear (and this matches what reshape will do).
 870 if (m_drawingBuffer) {
 871 m_drawingBuffer->reset(IntSize(width, height));
 872 restoreStateAfterClear();
 873 } else
 874 m_context->reshape(width, height);
 875
 876 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].texture2DBinding.get()));
 877 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get()));
 878 if (m_framebufferBinding)
 879 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
 880}
 881
 882int WebGLRenderingContextBase::drawingBufferWidth() const
 883{
 884 if (m_drawingBuffer)
 885 return m_drawingBuffer->size().width();
 886
 887 return m_context->getInternalFramebufferSize().width();
 888}
 889
 890int WebGLRenderingContextBase::drawingBufferHeight() const
 891{
 892 if (m_drawingBuffer)
 893 return m_drawingBuffer->size().height();
 894
 895 return m_context->getInternalFramebufferSize().height();
 896}
 897
 898unsigned WebGLRenderingContextBase::sizeInBytes(GC3Denum type)
 899{
 900 switch (type) {
 901 case GraphicsContext3D::BYTE:
 902 return sizeof(GC3Dbyte);
 903 case GraphicsContext3D::UNSIGNED_BYTE:
 904 return sizeof(GC3Dubyte);
 905 case GraphicsContext3D::SHORT:
 906 return sizeof(GC3Dshort);
 907 case GraphicsContext3D::UNSIGNED_SHORT:
 908 return sizeof(GC3Dushort);
 909 case GraphicsContext3D::INT:
 910 return sizeof(GC3Dint);
 911 case GraphicsContext3D::UNSIGNED_INT:
 912 return sizeof(GC3Duint);
 913 case GraphicsContext3D::FLOAT:
 914 return sizeof(GC3Dfloat);
 915 }
 916 ASSERT_NOT_REACHED();
 917 return 0;
 918}
 919
 920void WebGLRenderingContextBase::activeTexture(GC3Denum texture, ExceptionCode& ec)
 921{
 922 UNUSED_PARAM(ec);
 923 if (isContextLostOrPending())
 924 return;
 925 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
 926 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range");
 927 return;
 928 }
 929 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
 930 m_context->activeTexture(texture);
 931
 932 if (m_drawingBuffer)
 933 m_drawingBuffer->setActiveTextureUnit(texture);
 934}
 935
 936void WebGLRenderingContextBase::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
 937{
 938 UNUSED_PARAM(ec);
 939 if (isContextLostOrPending() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader))
 940 return;
 941 if (!program->attachShader(shader)) {
 942 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
 943 return;
 944 }
 945 m_context->attachShader(objectOrZero(program), objectOrZero(shader));
 946 shader->onAttached();
 947}
 948
 949void WebGLRenderingContextBase::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
 950{
 951 UNUSED_PARAM(ec);
 952 if (isContextLostOrPending() || !validateWebGLObject("bindAttribLocation", program))
 953 return;
 954 if (!validateLocationLength("bindAttribLocation", name))
 955 return;
 956 if (!validateString("bindAttribLocation", name))
 957 return;
 958 if (isPrefixReserved(name)) {
 959 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix");
 960 return;
 961 }
 962 if (index >= m_maxVertexAttribs) {
 963 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range");
 964 return;
 965 }
 966 m_context->bindAttribLocation(objectOrZero(program), index, name);
 967}
 968
 969bool WebGLRenderingContextBase::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted)
 970{
 971 deleted = false;
 972 if (isContextLostOrPending())
 973 return false;
 974 if (object) {
 975 if (!object->validate(contextGroup(), this)) {
 976 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context");
 977 return false;
 978 }
 979 deleted = !object->object();
 980 }
 981 return true;
 982}
 983
 984void WebGLRenderingContextBase::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
 985{
 986 UNUSED_PARAM(ec);
 987 bool deleted;
 988 if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
 989 return;
 990 if (deleted)
 991 buffer = 0;
 992 if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
 993 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets");
 994 return;
 995 }
 996 if (target == GraphicsContext3D::ARRAY_BUFFER)
 997 m_boundArrayBuffer = buffer;
 998 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
 999 m_boundVertexArrayObject->setElementArrayBuffer(buffer);
 1000 else {
 1001 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target");
 1002 return;
 1003 }
 1004
 1005 m_context->bindBuffer(target, objectOrZero(buffer));
 1006 if (buffer)
 1007 buffer->setTarget(target);
 1008}
 1009
 1010void WebGLRenderingContextBase::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
 1011{
 1012 UNUSED_PARAM(ec);
 1013 bool deleted;
 1014 if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
 1015 return;
 1016 if (deleted)
 1017 buffer = 0;
 1018 if (target != GraphicsContext3D::FRAMEBUFFER) {
 1019 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
 1020 return;
 1021 }
 1022 m_framebufferBinding = buffer;
 1023 if (m_drawingBuffer)
 1024 m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get()));
 1025 if (!m_framebufferBinding && m_drawingBuffer) {
 1026 // Instead of binding fb 0, bind the drawing buffer.
 1027 m_drawingBuffer->bind();
 1028 } else
 1029 m_context->bindFramebuffer(target, objectOrZero(buffer));
 1030 if (buffer)
 1031 buffer->setHasEverBeenBound();
 1032 applyStencilTest();
 1033}
 1034
 1035void WebGLRenderingContextBase::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
 1036{
 1037 UNUSED_PARAM(ec);
 1038 bool deleted;
 1039 if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
 1040 return;
 1041 if (deleted)
 1042 renderBuffer = 0;
 1043 if (target != GraphicsContext3D::RENDERBUFFER) {
 1044 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target");
 1045 return;
 1046 }
 1047 m_renderbufferBinding = renderBuffer;
 1048 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
 1049 if (renderBuffer)
 1050 renderBuffer->setHasEverBeenBound();
 1051}
 1052
 1053void WebGLRenderingContextBase::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
 1054{
 1055 UNUSED_PARAM(ec);
 1056 bool deleted;
 1057 if (!checkObjectToBeBound("bindTexture", texture, deleted))
 1058 return;
 1059 if (deleted)
 1060 texture = 0;
 1061 if (texture && texture->getTarget() && texture->getTarget() != target) {
 1062 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets");
 1063 return;
 1064 }
 1065 GC3Dint maxLevel = 0;
 1066 if (target == GraphicsContext3D::TEXTURE_2D) {
 1067 m_textureUnits[m_activeTextureUnit].texture2DBinding = texture;
 1068 maxLevel = m_maxTextureLevel;
 1069
 1070 if (m_drawingBuffer && !m_activeTextureUnit)
 1071 m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
 1072
 1073 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
 1074 m_textureUnits[m_activeTextureUnit].textureCubeMapBinding = texture;
 1075 maxLevel = m_maxCubeMapTextureLevel;
 1076 } else {
 1077 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target");
 1078 return;
 1079 }
 1080 m_context->bindTexture(target, objectOrZero(texture));
 1081 if (texture)
 1082 texture->setTarget(target, maxLevel);
 1083
 1084 // Note: previously we used to automatically set the TEXTURE_WRAP_R
 1085 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
 1086 // ES 2.0 doesn't expose this flag (a bug in the specification) and
 1087 // otherwise the application has no control over the seams in this
 1088 // dimension. However, it appears that supporting this properly on all
 1089 // platforms is fairly involved (will require a HashMap from texture ID
 1090 // in all ports), and we have not had any complaints, so the logic has
 1091 // been removed.
 1092}
 1093
 1094void WebGLRenderingContextBase::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
 1095{
 1096 if (isContextLostOrPending())
 1097 return;
 1098 m_context->blendColor(red, green, blue, alpha);
 1099}
 1100
 1101void WebGLRenderingContextBase::blendEquation(GC3Denum mode)
 1102{
 1103 if (isContextLostOrPending() || !validateBlendEquation("blendEquation", mode))
 1104 return;
 1105 m_context->blendEquation(mode);
 1106}
 1107
 1108void WebGLRenderingContextBase::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
 1109{
 1110 if (isContextLostOrPending() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha))
 1111 return;
 1112 m_context->blendEquationSeparate(modeRGB, modeAlpha);
 1113}
 1114
 1115
 1116void WebGLRenderingContextBase::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
 1117{
 1118 if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor))
 1119 return;
 1120 m_context->blendFunc(sfactor, dfactor);
 1121}
 1122
 1123void WebGLRenderingContextBase::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
 1124{
 1125 // Note: Alpha does not have the same restrictions as RGB.
 1126 if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB))
 1127 return;
 1128 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
 1129}
 1130
 1131void WebGLRenderingContextBase::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
 1132{
 1133 UNUSED_PARAM(ec);
 1134 if (isContextLostOrPending())
 1135 return;
 1136 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
 1137 if (!buffer)
 1138 return;
 1139 if (size < 0) {
 1140 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
 1141 return;
 1142 }
 1143 if (!size) {
 1144 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0");
 1145 return;
 1146 }
 1147 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1148 if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
 1149 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
 1150 return;
 1151 }
 1152 }
 1153
 1154 m_context->moveErrorsToSyntheticErrorList();
 1155 m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
 1156 if (m_context->moveErrorsToSyntheticErrorList()) {
 1157 // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1158 buffer->disassociateBufferData();
 1159 }
 1160}
 1161
 1162void WebGLRenderingContextBase::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
 1163{
 1164 UNUSED_PARAM(ec);
 1165 if (isContextLostOrPending())
 1166 return;
 1167 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
 1168 if (!buffer)
 1169 return;
 1170 if (!data) {
 1171 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
 1172 return;
 1173 }
 1174 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1175 if (!buffer->associateBufferData(data)) {
 1176 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
 1177 return;
 1178 }
 1179 }
 1180
 1181 m_context->moveErrorsToSyntheticErrorList();
 1182 m_context->bufferData(target, data->byteLength(), data->data(), usage);
 1183 if (m_context->moveErrorsToSyntheticErrorList()) {
 1184 // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1185 buffer->disassociateBufferData();
 1186 }
 1187}
 1188
 1189void WebGLRenderingContextBase::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
 1190{
 1191 UNUSED_PARAM(ec);
 1192 if (isContextLostOrPending())
 1193 return;
 1194 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
 1195 if (!buffer)
 1196 return;
 1197 if (!data) {
 1198 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
 1199 return;
 1200 }
 1201 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1202 if (!buffer->associateBufferData(data)) {
 1203 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
 1204 return;
 1205 }
 1206 }
 1207
 1208 m_context->moveErrorsToSyntheticErrorList();
 1209 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
 1210 if (m_context->moveErrorsToSyntheticErrorList()) {
 1211 // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1212 buffer->disassociateBufferData();
 1213 }
 1214}
 1215
 1216void WebGLRenderingContextBase::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
 1217{
 1218 UNUSED_PARAM(ec);
 1219 if (isContextLostOrPending())
 1220 return;
 1221 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
 1222 if (!buffer)
 1223 return;
 1224 if (offset < 0) {
 1225 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
 1226 return;
 1227 }
 1228 if (!data)
 1229 return;
 1230 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1231 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
 1232 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
 1233 return;
 1234 }
 1235 }
 1236
 1237 m_context->moveErrorsToSyntheticErrorList();
 1238 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
 1239 if (m_context->moveErrorsToSyntheticErrorList()) {
 1240 // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1241 buffer->disassociateBufferData();
 1242 }
 1243}
 1244
 1245void WebGLRenderingContextBase::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
 1246{
 1247 UNUSED_PARAM(ec);
 1248 if (isContextLostOrPending())
 1249 return;
 1250 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
 1251 if (!buffer)
 1252 return;
 1253 if (offset < 0) {
 1254 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
 1255 return;
 1256 }
 1257 if (!data)
 1258 return;
 1259 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 1260 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
 1261 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
 1262 return;
 1263 }
 1264 }
 1265
 1266 m_context->moveErrorsToSyntheticErrorList();
 1267 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
 1268 if (m_context->moveErrorsToSyntheticErrorList()) {
 1269 // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
 1270 buffer->disassociateBufferData();
 1271 }
 1272}
 1273
 1274GC3Denum WebGLRenderingContextBase::checkFramebufferStatus(GC3Denum target)
 1275{
 1276 if (isContextLostOrPending())
 1277 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
 1278 if (target != GraphicsContext3D::FRAMEBUFFER) {
 1279 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
 1280 return 0;
 1281 }
 1282 if (!m_framebufferBinding || !m_framebufferBinding->object())
 1283 return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
 1284 const char* reason = "framebuffer incomplete";
 1285 GC3Denum result = m_framebufferBinding->checkStatus(&reason);
 1286 if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
 1287 printGLWarningToConsole("checkFramebufferStatus", reason);
 1288 return result;
 1289 }
 1290 result = m_context->checkFramebufferStatus(target);
 1291 return result;
 1292}
 1293
 1294void WebGLRenderingContextBase::clear(GC3Dbitfield mask)
 1295{
 1296 if (isContextLostOrPending())
 1297 return;
 1298 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
 1299 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
 1300 return;
 1301 }
 1302 const char* reason = "framebuffer incomplete";
 1303 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 1304 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
 1305 return;
 1306 }
 1307 if (!clearIfComposited(mask))
 1308 m_context->clear(mask);
 1309 markContextChanged();
 1310}
 1311
 1312void WebGLRenderingContextBase::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
 1313{
 1314 if (isContextLostOrPending())
 1315 return;
 1316 if (std::isnan(r))
 1317 r = 0;
 1318 if (std::isnan(g))
 1319 g = 0;
 1320 if (std::isnan(b))
 1321 b = 0;
 1322 if (std::isnan(a))
 1323 a = 1;
 1324 m_clearColor[0] = r;
 1325 m_clearColor[1] = g;
 1326 m_clearColor[2] = b;
 1327 m_clearColor[3] = a;
 1328 m_context->clearColor(r, g, b, a);
 1329}
 1330
 1331void WebGLRenderingContextBase::clearDepth(GC3Dfloat depth)
 1332{
 1333 if (isContextLostOrPending())
 1334 return;
 1335 m_clearDepth = depth;
 1336 m_context->clearDepth(depth);
 1337}
 1338
 1339void WebGLRenderingContextBase::clearStencil(GC3Dint s)
 1340{
 1341 if (isContextLostOrPending())
 1342 return;
 1343 m_clearStencil = s;
 1344 m_context->clearStencil(s);
 1345}
 1346
 1347void WebGLRenderingContextBase::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
 1348{
 1349 if (isContextLostOrPending())
 1350 return;
 1351 m_colorMask[0] = red;
 1352 m_colorMask[1] = green;
 1353 m_colorMask[2] = blue;
 1354 m_colorMask[3] = alpha;
 1355 m_context->colorMask(red, green, blue, alpha);
 1356}
 1357
 1358void WebGLRenderingContextBase::compileShader(WebGLShader* shader, ExceptionCode& ec)
 1359{
 1360 UNUSED_PARAM(ec);
 1361 if (isContextLostOrPending() || !validateWebGLObject("compileShader", shader))
 1362 return;
 1363 m_context->compileShader(objectOrZero(shader));
 1364 GC3Dint value;
 1365 m_context->getShaderiv(objectOrZero(shader), GraphicsContext3D::COMPILE_STATUS, &value);
 1366 shader->setValid(value);
 1367}
 1368
 1369void WebGLRenderingContextBase::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
 1370 GC3Dsizei height, GC3Dint border, ArrayBufferView* data)
 1371{
 1372 if (isContextLostOrPending())
 1373 return;
 1374 if (!validateTexFuncLevel("compressedTexImage2D", target, level))
 1375 return;
 1376
 1377 if (!validateCompressedTexFormat(internalformat)) {
 1378 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat");
 1379 return;
 1380 }
 1381 if (border) {
 1382 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0");
 1383 return;
 1384 }
 1385 if (!validateCompressedTexDimensions("compressedTexImage2D", target, level, width, height, internalformat))
 1386 return;
 1387 if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data))
 1388 return;
 1389
 1390 WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true);
 1391 if (!tex)
 1392 return;
 1393 if (!isGLES2NPOTStrict()) {
 1394 if (level && WebGLTexture::isNPOT(width, height)) {
 1395 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2");
 1396 return;
 1397 }
 1398 }
 1399 m_context->moveErrorsToSyntheticErrorList();
 1400 m_context->compressedTexImage2D(target, level, internalformat, width, height,
 1401 border, data->byteLength(), data->baseAddress());
 1402 if (m_context->moveErrorsToSyntheticErrorList()) {
 1403 // The compressedTexImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
 1404 tex->markInvalid(target, level);
 1405 return;
 1406 }
 1407
 1408 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
 1409 tex->setCompressed();
 1410}
 1411
 1412void WebGLRenderingContextBase::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 1413 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data)
 1414{
 1415 if (isContextLostOrPending())
 1416 return;
 1417 if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
 1418 return;
 1419 if (!validateCompressedTexFormat(format)) {
 1420 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format");
 1421 return;
 1422 }
 1423 if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
 1424 return;
 1425
 1426 WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true);
 1427 if (!tex)
 1428 return;
 1429
 1430 if (format != tex->getInternalFormat(target, level)) {
 1431 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format");
 1432 return;
 1433 }
 1434
 1435 if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex))
 1436 return;
 1437
 1438 graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset,
 1439 width, height, format, data->byteLength(), data->baseAddress());
 1440 tex->setCompressed();
 1441}
 1442
 1443bool WebGLRenderingContextBase::validateSettableTexFormat(const char* functionName, GC3Denum format)
 1444{
 1445 if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
 1446 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
 1447 return false;
 1448 }
 1449 return true;
 1450}
 1451
 1452void WebGLRenderingContextBase::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
 1453{
 1454 if (isContextLostOrPending())
 1455 return;
 1456 if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
 1457 return;
 1458 if (!validateSettableTexFormat("copyTexImage2D", internalformat))
 1459 return;
 1460 WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
 1461 if (!tex)
 1462 return;
 1463 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
 1464 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
 1465 return;
 1466 }
 1467 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
 1468 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
 1469 return;
 1470 }
 1471 const char* reason = "framebuffer incomplete";
 1472 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 1473 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
 1474 return;
 1475 }
 1476 clearIfComposited();
 1477 if (isResourceSafe()) {
 1478 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1479 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
 1480 } else {
 1481 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1482 GC3Dint clippedX, clippedY;
 1483 GC3Dsizei clippedWidth, clippedHeight;
 1484 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
 1485 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
 1486 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
 1487 if (clippedWidth > 0 && clippedHeight > 0) {
 1488 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
 1489 clippedX, clippedY, clippedWidth, clippedHeight);
 1490 }
 1491 } else
 1492 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
 1493 }
 1494 // FIXME: if the framebuffer is not complete, none of the below should be executed.
 1495 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
 1496}
 1497
 1498void WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 1499{
 1500 if (isContextLostOrPending())
 1501 return;
 1502 if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
 1503 return;
 1504 WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true);
 1505 if (!tex)
 1506 return;
 1507 if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height))
 1508 return;
 1509 // Before checking if it is in the range, check if overflow happens first.
 1510 if (xoffset + width < 0 || yoffset + height < 0) {
 1511 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions");
 1512 return;
 1513 }
 1514 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
 1515 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
 1516 return;
 1517 }
 1518 GC3Denum internalformat = tex->getInternalFormat(target, level);
 1519 if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
 1520 return;
 1521 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
 1522 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
 1523 return;
 1524 }
 1525 const char* reason = "framebuffer incomplete";
 1526 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 1527 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
 1528 return;
 1529 }
 1530 clearIfComposited();
 1531 if (isResourceSafe()) {
 1532 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1533 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 1534 } else {
 1535 GC3Dint clippedX, clippedY;
 1536 GC3Dsizei clippedWidth, clippedHeight;
 1537 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
 1538 GC3Denum format = tex->getInternalFormat(target, level);
 1539 GC3Denum type = tex->getType(target, level);
 1540 std::unique_ptr<unsigned char[]> zero;
 1541 if (width && height) {
 1542 unsigned size;
 1543 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
 1544 if (error != GraphicsContext3D::NO_ERROR) {
 1545 synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
 1546 return;
 1547 }
 1548 zero = std::make_unique<unsigned char[]>(size);
 1549 if (!zero) {
 1550 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory");
 1551 return;
 1552 }
 1553 memset(zero.get(), 0, size);
 1554 }
 1555 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
 1556 if (clippedWidth > 0 && clippedHeight > 0) {
 1557 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1558 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
 1559 clippedX, clippedY, clippedWidth, clippedHeight);
 1560 }
 1561 } else {
 1562 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 1563 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 1564 }
 1565 }
 1566}
 1567
 1568PassRefPtr<WebGLBuffer> WebGLRenderingContextBase::createBuffer()
 1569{
 1570 if (isContextLostOrPending())
 1571 return nullptr;
 1572 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
 1573 addSharedObject(o.get());
 1574 return o;
 1575}
 1576
 1577PassRefPtr<WebGLFramebuffer> WebGLRenderingContextBase::createFramebuffer()
 1578{
 1579 if (isContextLostOrPending())
 1580 return nullptr;
 1581 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
 1582 addContextObject(o.get());
 1583 return o;
 1584}
 1585
 1586PassRefPtr<WebGLTexture> WebGLRenderingContextBase::createTexture()
 1587{
 1588 if (isContextLostOrPending())
 1589 return nullptr;
 1590 RefPtr<WebGLTexture> o = WebGLTexture::create(this);
 1591 addSharedObject(o.get());
 1592 return o;
 1593}
 1594
 1595PassRefPtr<WebGLProgram> WebGLRenderingContextBase::createProgram()
 1596{
 1597 if (isContextLostOrPending())
 1598 return nullptr;
 1599 RefPtr<WebGLProgram> o = WebGLProgram::create(this);
 1600 addSharedObject(o.get());
 1601 return o;
 1602}
 1603
 1604PassRefPtr<WebGLRenderbuffer> WebGLRenderingContextBase::createRenderbuffer()
 1605{
 1606 if (isContextLostOrPending())
 1607 return nullptr;
 1608 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
 1609 addSharedObject(o.get());
 1610 return o;
 1611}
 1612
 1613PassRefPtr<WebGLShader> WebGLRenderingContextBase::createShader(GC3Denum type, ExceptionCode& ec)
 1614{
 1615 UNUSED_PARAM(ec);
 1616 if (isContextLostOrPending())
 1617 return nullptr;
 1618 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
 1619 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type");
 1620 return nullptr;
 1621 }
 1622
 1623 RefPtr<WebGLShader> o = WebGLShader::create(this, type);
 1624 addSharedObject(o.get());
 1625 return o;
 1626}
 1627
 1628void WebGLRenderingContextBase::cullFace(GC3Denum mode)
 1629{
 1630 if (isContextLostOrPending())
 1631 return;
 1632 m_context->cullFace(mode);
 1633}
 1634
 1635bool WebGLRenderingContextBase::deleteObject(WebGLObject* object)
 1636{
 1637 if (isContextLostOrPending() || !object)
 1638 return false;
 1639 if (!object->validate(contextGroup(), this)) {
 1640 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context");
 1641 return false;
 1642 }
 1643 if (object->object()) {
 1644 // We need to pass in context here because we want
 1645 // things in this context unbound.
 1646 object->deleteObject(graphicsContext3D());
 1647 }
 1648 return true;
 1649}
 1650
 1651void WebGLRenderingContextBase::deleteBuffer(WebGLBuffer* buffer)
 1652{
 1653 if (!deleteObject(buffer))
 1654 return;
 1655 if (m_boundArrayBuffer == buffer)
 1656 m_boundArrayBuffer = 0;
 1657
 1658 m_boundVertexArrayObject->unbindBuffer(buffer);
 1659}
 1660
 1661void WebGLRenderingContextBase::deleteFramebuffer(WebGLFramebuffer* framebuffer)
 1662{
 1663 if (!deleteObject(framebuffer))
 1664 return;
 1665 if (framebuffer == m_framebufferBinding) {
 1666 m_framebufferBinding = 0;
 1667 if (m_drawingBuffer) {
 1668 m_drawingBuffer->setFramebufferBinding(0);
 1669 // Have to call bindFramebuffer here to bind back to internal fbo.
 1670 m_drawingBuffer->bind();
 1671 } else
 1672 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
 1673 }
 1674}
 1675
 1676void WebGLRenderingContextBase::deleteProgram(WebGLProgram* program)
 1677{
 1678 deleteObject(program);
 1679 // We don't reset m_currentProgram to 0 here because the deletion of the
 1680 // current program is delayed.
 1681}
 1682
 1683void WebGLRenderingContextBase::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
 1684{
 1685 if (!deleteObject(renderbuffer))
 1686 return;
 1687 if (renderbuffer == m_renderbufferBinding)
 1688 m_renderbufferBinding = 0;
 1689 if (m_framebufferBinding)
 1690 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
 1691}
 1692
 1693void WebGLRenderingContextBase::deleteShader(WebGLShader* shader)
 1694{
 1695 deleteObject(shader);
 1696}
 1697
 1698void WebGLRenderingContextBase::deleteTexture(WebGLTexture* texture)
 1699{
 1700 if (!deleteObject(texture))
 1701 return;
 1702 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
 1703 if (texture == m_textureUnits[i].texture2DBinding)
 1704 m_textureUnits[i].texture2DBinding = nullptr;
 1705 if (texture == m_textureUnits[i].textureCubeMapBinding)
 1706 m_textureUnits[i].textureCubeMapBinding = nullptr;
 1707 }
 1708 if (m_framebufferBinding)
 1709 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
 1710}
 1711
 1712void WebGLRenderingContextBase::depthFunc(GC3Denum func)
 1713{
 1714 if (isContextLostOrPending())
 1715 return;
 1716 m_context->depthFunc(func);
 1717}
 1718
 1719void WebGLRenderingContextBase::depthMask(GC3Dboolean flag)
 1720{
 1721 if (isContextLostOrPending())
 1722 return;
 1723 m_depthMask = flag;
 1724 m_context->depthMask(flag);
 1725}
 1726
 1727void WebGLRenderingContextBase::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
 1728{
 1729 if (isContextLostOrPending())
 1730 return;
 1731 if (zNear > zFar) {
 1732 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar");
 1733 return;
 1734 }
 1735 m_context->depthRange(zNear, zFar);
 1736}
 1737
 1738void WebGLRenderingContextBase::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
 1739{
 1740 UNUSED_PARAM(ec);
 1741 if (isContextLostOrPending() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader))
 1742 return;
 1743 if (!program->detachShader(shader)) {
 1744 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
 1745 return;
 1746 }
 1747 m_context->detachShader(objectOrZero(program), objectOrZero(shader));
 1748 shader->onDetached(graphicsContext3D());
 1749}
 1750
 1751void WebGLRenderingContextBase::disable(GC3Denum cap)
 1752{
 1753 if (isContextLostOrPending() || !validateCapability("disable", cap))
 1754 return;
 1755 if (cap == GraphicsContext3D::STENCIL_TEST) {
 1756 m_stencilEnabled = false;
 1757 applyStencilTest();
 1758 return;
 1759 }
 1760 if (cap == GraphicsContext3D::SCISSOR_TEST) {
 1761 m_scissorEnabled = false;
 1762 if (m_drawingBuffer)
 1763 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
 1764 }
 1765 m_context->disable(cap);
 1766}
 1767
 1768void WebGLRenderingContextBase::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
 1769{
 1770 UNUSED_PARAM(ec);
 1771 if (isContextLostOrPending())
 1772 return;
 1773 if (index >= m_maxVertexAttribs) {
 1774 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range");
 1775 return;
 1776 }
 1777
 1778 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
 1779 state.enabled = false;
 1780
 1781 if (index > 0 || isGLES2Compliant())
 1782 m_context->disableVertexAttribArray(index);
 1783}
 1784
 1785bool WebGLRenderingContextBase::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
 1786{
 1787 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
 1788
 1789 if (!elementArrayBuffer)
 1790 return false;
 1791
 1792 if (offset < 0)
 1793 return false;
 1794
 1795 if (type == GraphicsContext3D::UNSIGNED_INT) {
 1796 // For an unsigned array, offset must be divisible by 4 for alignment reasons.
 1797 if (offset % 4)
 1798 return false;
 1799
 1800 // Make uoffset an element offset.
 1801 offset /= 4;
 1802
 1803 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 4;
 1804 if (offset > n || count > n - offset)
 1805 return false;
 1806 } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
 1807 // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
 1808 if (offset % 2)
 1809 return false;
 1810
 1811 // Make uoffset an element offset.
 1812 offset /= 2;
 1813
 1814 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
 1815 if (offset > n || count > n - offset)
 1816 return false;
 1817 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
 1818 GC3Dsizeiptr n = elementArrayBuffer->byteLength();
 1819 if (offset > n || count > n - offset)
 1820 return false;
 1821 }
 1822 return true;
 1823}
 1824
 1825bool WebGLRenderingContextBase::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
 1826{
 1827 // Performs conservative validation by caching a maximum index of
 1828 // the given type per element array buffer. If all of the bound
 1829 // array buffers have enough elements to satisfy that maximum
 1830 // index, skips the expensive per-draw-call iteration in
 1831 // validateIndexArrayPrecise.
 1832
 1833 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
 1834
 1835 if (!elementArrayBuffer)
 1836 return false;
 1837
 1838 GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
 1839 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
 1840 if (!numElements)
 1841 return false;
 1842 const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
 1843 ASSERT(buffer);
 1844
 1845 int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
 1846 if (maxIndex < 0) {
 1847 // Compute the maximum index in the entire buffer for the given type of index.
 1848 switch (type) {
 1849 case GraphicsContext3D::UNSIGNED_BYTE: {
 1850 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
 1851 for (GC3Dsizeiptr i = 0; i < numElements; i++)
 1852 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
 1853 break;
 1854 }
 1855 case GraphicsContext3D::UNSIGNED_SHORT: {
 1856 numElements /= sizeof(GC3Dushort);
 1857 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
 1858 for (GC3Dsizeiptr i = 0; i < numElements; i++)
 1859 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
 1860 break;
 1861 }
 1862 case GraphicsContext3D::UNSIGNED_INT: {
 1863 if (!m_oesElementIndexUint)
 1864 return false;
 1865 numElements /= sizeof(GC3Duint);
 1866 const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
 1867 for (GC3Dsizeiptr i = 0; i < numElements; i++)
 1868 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
 1869 break;
 1870 }
 1871 default:
 1872 return false;
 1873 }
 1874 elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
 1875 }
 1876
 1877 if (maxIndex >= 0) {
 1878 // The number of required elements is one more than the maximum
 1879 // index that will be accessed.
 1880 numElementsRequired = maxIndex + 1;
 1881 return true;
 1882 }
 1883
 1884 return false;
 1885}
 1886
 1887bool WebGLRenderingContextBase::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired)
 1888{
 1889 ASSERT(count >= 0 && offset >= 0);
 1890 unsigned lastIndex = 0;
 1891
 1892 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
 1893
 1894 if (!elementArrayBuffer)
 1895 return false;
 1896
 1897 if (!count) {
 1898 numElementsRequired = 0;
 1899 return true;
 1900 }
 1901
 1902 if (!elementArrayBuffer->elementArrayBuffer())
 1903 return false;
 1904
 1905 unsigned long uoffset = offset;
 1906 unsigned long n = count;
 1907
 1908 if (type == GraphicsContext3D::UNSIGNED_INT) {
 1909 // Make uoffset an element offset.
 1910 uoffset /= sizeof(GC3Duint);
 1911 const GC3Duint* p = static_cast<const GC3Duint*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
 1912 while (n-- > 0) {
 1913 if (*p > lastIndex)
 1914 lastIndex = *p;
 1915 ++p;
 1916 }
 1917 } else if (type == GraphicsContext3D::UNSIGNED_SHORT) {
 1918 // Make uoffset an element offset.
 1919 uoffset /= sizeof(GC3Dushort);
 1920 const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
 1921 while (n-- > 0) {
 1922 if (*p > lastIndex)
 1923 lastIndex = *p;
 1924 ++p;
 1925 }
 1926 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
 1927 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
 1928 while (n-- > 0) {
 1929 if (*p > lastIndex)
 1930 lastIndex = *p;
 1931 ++p;
 1932 }
 1933 }
 1934
 1935 // Then set the last index in the index array and make sure it is valid.
 1936 numElementsRequired = lastIndex + 1;
 1937 return numElementsRequired > 0;
 1938}
 1939
 1940bool WebGLRenderingContextBase::validateVertexAttributes(unsigned elementCount, unsigned primitiveCount)
 1941{
 1942 if (!m_currentProgram)
 1943 return false;
 1944
 1945 // Look in each enabled vertex attrib and check if they've been bound to a buffer.
 1946 for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
 1947 if (!m_boundVertexArrayObject->getVertexAttribState(i).validateBinding())
 1948 return false;
 1949 }
 1950
 1951 if (elementCount <= 0)
 1952 return true;
 1953
 1954
 1955 // Look in each consumed vertex attrib (by the current program).
 1956 bool sawNonInstancedAttrib = false;
 1957 bool sawEnabledAttrib = false;
 1958 int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
 1959 for (int i = 0; i < numActiveAttribLocations; ++i) {
 1960 int loc = m_currentProgram->getActiveAttribLocation(i);
 1961 if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
 1962 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
 1963 if (state.enabled) {
 1964 sawEnabledAttrib = true;
 1965 // Avoid off-by-one errors in numElements computation.
 1966 // For the last element, we will only touch the data for the
 1967 // element and nothing beyond it.
 1968 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
 1969 unsigned numElements = 0;
 1970 ASSERT(state.stride > 0);
 1971 if (bytesRemaining >= state.bytesPerElement)
 1972 numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
 1973 unsigned instancesRequired = 0;
 1974 if (state.divisor) {
 1975 instancesRequired = ceil(static_cast<float>(primitiveCount) / state.divisor);
 1976 if (instancesRequired > numElements)
 1977 return false;
 1978 } else {
 1979 sawNonInstancedAttrib = true;
 1980 if (elementCount > numElements)
 1981 return false;
 1982 }
 1983 }
 1984 }
 1985 }
 1986
 1987 if (!sawNonInstancedAttrib && sawEnabledAttrib)
 1988 return false;
 1989
 1990 return true;
 1991}
 1992
 1993bool WebGLRenderingContextBase::validateWebGLObject(const char* functionName, WebGLObject* object)
 1994{
 1995 if (!object || !object->object()) {
 1996 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted");
 1997 return false;
 1998 }
 1999 if (!object->validate(contextGroup(), this)) {
 2000 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context");
 2001 return false;
 2002 }
 2003 return true;
 2004}
 2005
 2006bool WebGLRenderingContextBase::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primitiveCount)
 2007{
 2008 if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
 2009 return false;
 2010
 2011 if (!validateStencilSettings(functionName))
 2012 return false;
 2013
 2014 if (first < 0 || count < 0) {
 2015 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0");
 2016 return false;
 2017 }
 2018
 2019 if (!count) {
 2020 markContextChanged();
 2021 return false;
 2022 }
 2023
 2024 if (primitiveCount < 0) {
 2025 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
 2026 return false;
 2027 }
 2028
 2029 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 2030 // Ensure we have a valid rendering state
 2031 Checked<GC3Dint, RecordOverflow> checkedFirst(first);
 2032 Checked<GC3Dint, RecordOverflow> checkedCount(count);
 2033 Checked<GC3Dint, RecordOverflow> checkedSum = checkedFirst + checkedCount;
 2034 Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount);
 2035 if (checkedSum.hasOverflowed() || checkedPrimitiveCount.hasOverflowed() || !validateVertexAttributes(checkedSum.unsafeGet(), checkedPrimitiveCount.unsafeGet())) {
 2036 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
 2037 return false;
 2038 }
 2039 } else {
 2040 if (!validateVertexAttributes(0)) {
 2041 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
 2042 return false;
 2043 }
 2044 }
 2045
 2046 const char* reason = "framebuffer incomplete";
 2047 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 2048 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
 2049 return false;
 2050 }
 2051
 2052 return true;
 2053}
 2054
 2055void WebGLRenderingContextBase::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
 2056{
 2057 UNUSED_PARAM(ec);
 2058
 2059 if (!validateDrawArrays("drawArrays", mode, first, count, 0))
 2060 return;
 2061
 2062 clearIfComposited();
 2063
 2064 bool vertexAttrib0Simulated = false;
 2065 if (!isGLES2Compliant())
 2066 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
 2067 if (!isGLES2NPOTStrict())
 2068 checkTextureCompleteness("drawArrays", true);
 2069
 2070 m_context->drawArrays(mode, first, count);
 2071
 2072 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 2073 restoreStatesAfterVertexAttrib0Simulation();
 2074 if (!isGLES2NPOTStrict())
 2075 checkTextureCompleteness("drawArrays", false);
 2076 markContextChanged();
 2077}
 2078
 2079bool WebGLRenderingContextBase::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primitiveCount)
 2080{
 2081 if (isContextLostOrPending() || !validateDrawMode(functionName, mode))
 2082 return false;
 2083
 2084 if (!validateStencilSettings(functionName))
 2085 return false;
 2086
 2087 switch (type) {
 2088 case GraphicsContext3D::UNSIGNED_BYTE:
 2089 case GraphicsContext3D::UNSIGNED_SHORT:
 2090 break;
 2091 case GraphicsContext3D::UNSIGNED_INT:
 2092 if (m_oesElementIndexUint)
 2093 break;
 2094 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
 2095 return false;
 2096 default:
 2097 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type");
 2098 return false;
 2099 }
 2100
 2101 if (count < 0 || offset < 0) {
 2102 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0");
 2103 return false;
 2104 }
 2105
 2106 if (!count) {
 2107 markContextChanged();
 2108 return false;
 2109 }
 2110
 2111 if (primitiveCount < 0) {
 2112 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0");
 2113 return false;
 2114 }
 2115
 2116 if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
 2117 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound");
 2118 return false;
 2119 }
 2120
 2121 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
 2122 // Ensure we have a valid rendering state
 2123 if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
 2124 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "request out of bounds for current ELEMENT_ARRAY_BUFFER");
 2125 return false;
 2126 }
 2127 if (!count)
 2128 return false;
 2129
 2130 Checked<GC3Dint, RecordOverflow> checkedCount(count);
 2131 Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount);
 2132 if (checkedCount.hasOverflowed() || checkedPrimitiveCount.hasOverflowed()) {
 2133 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
 2134 return false;
 2135 }
 2136
 2137 if (!validateIndexArrayConservative(type, numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) {
 2138 if (!validateIndexArrayPrecise(checkedCount.unsafeGet(), type, static_cast<GC3Dintptr>(offset), numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) {
 2139 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays");
 2140 return false;
 2141 }
 2142 }
 2143 } else {
 2144 if (!validateVertexAttributes(0)) {
 2145 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly");
 2146 return false;
 2147 }
 2148 }
 2149
 2150 const char* reason = "framebuffer incomplete";
 2151 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 2152 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
 2153 return false;
 2154 }
 2155
 2156 return true;
 2157}
 2158
 2159void WebGLRenderingContextBase::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
 2160{
 2161 UNUSED_PARAM(ec);
 2162
 2163 unsigned numElements = 0;
 2164 if (!validateDrawElements("drawElements", mode, count, type, offset, numElements, 0))
 2165 return;
 2166
 2167 clearIfComposited();
 2168
 2169 bool vertexAttrib0Simulated = false;
 2170 if (!isGLES2Compliant()) {
 2171 if (!numElements)
 2172 validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
 2173 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
 2174 }
 2175 if (!isGLES2NPOTStrict())
 2176 checkTextureCompleteness("drawElements", true);
 2177
 2178 m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
 2179
 2180 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 2181 restoreStatesAfterVertexAttrib0Simulation();
 2182 if (!isGLES2NPOTStrict())
 2183 checkTextureCompleteness("drawElements", false);
 2184 markContextChanged();
 2185}
 2186
 2187void WebGLRenderingContextBase::enable(GC3Denum cap)
 2188{
 2189 if (isContextLostOrPending() || !validateCapability("enable", cap))
 2190 return;
 2191 if (cap == GraphicsContext3D::STENCIL_TEST) {
 2192 m_stencilEnabled = true;
 2193 applyStencilTest();
 2194 return;
 2195 }
 2196 if (cap == GraphicsContext3D::SCISSOR_TEST) {
 2197 m_scissorEnabled = true;
 2198 if (m_drawingBuffer)
 2199 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
 2200 }
 2201 m_context->enable(cap);
 2202}
 2203
 2204void WebGLRenderingContextBase::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
 2205{
 2206 UNUSED_PARAM(ec);
 2207 if (isContextLostOrPending())
 2208 return;
 2209 if (index >= m_maxVertexAttribs) {
 2210 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range");
 2211 return;
 2212 }
 2213
 2214 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
 2215 state.enabled = true;
 2216
 2217 m_context->enableVertexAttribArray(index);
 2218}
 2219
 2220void WebGLRenderingContextBase::finish()
 2221{
 2222 if (isContextLostOrPending())
 2223 return;
 2224 m_context->finish();
 2225}
 2226
 2227void WebGLRenderingContextBase::flush()
 2228{
 2229 if (isContextLostOrPending())
 2230 return;
 2231 m_context->flush();
 2232}
 2233
 2234void WebGLRenderingContextBase::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
 2235{
 2236 UNUSED_PARAM(ec);
 2237 if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment))
 2238 return;
 2239 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
 2240 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target");
 2241 return;
 2242 }
 2243 if (buffer && !buffer->validate(contextGroup(), this)) {
 2244 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
 2245 return;
 2246 }
 2247 // Don't allow the default framebuffer to be mutated; all current
 2248 // implementations use an FBO internally in place of the default
 2249 // FBO.
 2250 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
 2251 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
 2252 return;
 2253 }
 2254 Platform3DObject bufferObject = objectOrZero(buffer);
 2255 switch (attachment) {
 2256 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
 2257 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
 2258 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
 2259 break;
 2260 default:
 2261 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
 2262 }
 2263 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
 2264 applyStencilTest();
 2265}
 2266
 2267void WebGLRenderingContextBase::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
 2268{
 2269 UNUSED_PARAM(ec);
 2270 if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
 2271 return;
 2272 if (level) {
 2273 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
 2274 return;
 2275 }
 2276 if (texture && !texture->validate(contextGroup(), this)) {
 2277 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
 2278 return;
 2279 }
 2280 // Don't allow the default framebuffer to be mutated; all current
 2281 // implementations use an FBO internally in place of the default
 2282 // FBO.
 2283 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
 2284 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
 2285 return;
 2286 }
 2287 Platform3DObject textureObject = objectOrZero(texture);
 2288 switch (attachment) {
 2289 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
 2290 m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level);
 2291 m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level);
 2292 break;
 2293 case GraphicsContext3D::DEPTH_ATTACHMENT:
 2294 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
 2295 break;
 2296 case GraphicsContext3D::STENCIL_ATTACHMENT:
 2297 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
 2298 break;
 2299 default:
 2300 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
 2301 }
 2302 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
 2303 applyStencilTest();
 2304}
 2305
 2306void WebGLRenderingContextBase::frontFace(GC3Denum mode)
 2307{
 2308 if (isContextLostOrPending())
 2309 return;
 2310 m_context->frontFace(mode);
 2311}
 2312
 2313void WebGLRenderingContextBase::generateMipmap(GC3Denum target)
 2314{
 2315 if (isContextLostOrPending())
 2316 return;
 2317 WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
 2318 if (!tex)
 2319 return;
 2320 if (!tex->canGenerateMipmaps()) {
 2321 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size");
 2322 return;
 2323 }
 2324 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=123916. Compressed textures should be allowed in WebGL 2:
 2325 if (tex->isCompressed()) {
 2326 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture");
 2327 return;
 2328 }
 2329 if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
 2330 return;
 2331
 2332 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
 2333 // on Mac. Remove the hack once this driver bug is fixed.
 2334#if OS(DARWIN)
 2335 bool needToResetMinFilter = false;
 2336 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
 2337 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
 2338 needToResetMinFilter = true;
 2339 }
 2340#endif
 2341 m_context->generateMipmap(target);
 2342#if OS(DARWIN)
 2343 if (needToResetMinFilter)
 2344 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
 2345#endif
 2346 tex->generateMipmapLevelInfo();
 2347}
 2348
 2349PassRefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
 2350{
 2351 UNUSED_PARAM(ec);
 2352 if (isContextLostOrPending() || !validateWebGLObject("getActiveAttrib", program))
 2353 return nullptr;
 2354 ActiveInfo info;
 2355 if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
 2356 return nullptr;
 2357
 2358 LOG(WebGL, "Returning active attribute %d: %s", index, info.name.utf8().data());
 2359
 2360 return WebGLActiveInfo::create(info.name, info.type, info.size);
 2361}
 2362
 2363PassRefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
 2364{
 2365 UNUSED_PARAM(ec);
 2366 if (isContextLostOrPending() || !validateWebGLObject("getActiveUniform", program))
 2367 return 0;
 2368 ActiveInfo info;
 2369 if (!m_context->getActiveUniform(objectOrZero(program), index, info))
 2370 return nullptr;
 2371 if (!isGLES2Compliant()) {
 2372 if (info.size > 1 && !info.name.endsWith("[0]"))
 2373 info.name.append("[0]");
 2374 }
 2375
 2376 LOG(WebGL, "Returning active uniform %d: %s", index, info.name.utf8().data());
 2377
 2378 return WebGLActiveInfo::create(info.name, info.type, info.size);
 2379}
 2380
 2381bool WebGLRenderingContextBase::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader>>& shaderObjects, ExceptionCode& ec)
 2382{
 2383 UNUSED_PARAM(ec);
 2384 shaderObjects.clear();
 2385 if (isContextLostOrPending() || !validateWebGLObject("getAttachedShaders", program))
 2386 return false;
 2387
 2388 const GC3Denum shaderType[] = {
 2389 GraphicsContext3D::VERTEX_SHADER,
 2390 GraphicsContext3D::FRAGMENT_SHADER
 2391 };
 2392 for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
 2393 WebGLShader* shader = program->getAttachedShader(shaderType[i]);
 2394 if (shader)
 2395 shaderObjects.append(shader);
 2396 }
 2397 return true;
 2398}
 2399
 2400GC3Dint WebGLRenderingContextBase::getAttribLocation(WebGLProgram* program, const String& name)
 2401{
 2402 if (isContextLostOrPending() || !validateWebGLObject("getAttribLocation", program))
 2403 return -1;
 2404 if (!validateLocationLength("getAttribLocation", name))
 2405 return -1;
 2406 if (!validateString("getAttribLocation", name))
 2407 return -1;
 2408 if (isPrefixReserved(name))
 2409 return -1;
 2410 if (!program->getLinkStatus()) {
 2411 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked");
 2412 return -1;
 2413 }
 2414 return m_context->getAttribLocation(objectOrZero(program), name);
 2415}
 2416
 2417WebGLGetInfo WebGLRenderingContextBase::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
 2418{
 2419 UNUSED_PARAM(ec);
 2420 if (isContextLostOrPending())
 2421 return WebGLGetInfo();
 2422 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
 2423 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
 2424 return WebGLGetInfo();
 2425 }
 2426
 2427 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
 2428 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
 2429 return WebGLGetInfo();
 2430 }
 2431
 2432 GC3Dint value = 0;
 2433 m_context->getBufferParameteriv(target, pname, &value);
 2434 if (pname == GraphicsContext3D::BUFFER_SIZE)
 2435 return WebGLGetInfo(value);
 2436 return WebGLGetInfo(static_cast<unsigned>(value));
 2437}
 2438
 2439PassRefPtr<WebGLContextAttributes> WebGLRenderingContextBase::getContextAttributes()
 2440{
 2441 if (isContextLostOrPending())
 2442 return nullptr;
 2443 // We always need to return a new WebGLContextAttributes object to
 2444 // prevent the user from mutating any cached version.
 2445
 2446 // Also, we need to enforce requested values of "false" for depth
 2447 // and stencil, regardless of the properties of the underlying
 2448 // GraphicsContext3D or DrawingBuffer.
 2449 RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
 2450 if (!m_attributes.depth)
 2451 attributes->setDepth(false);
 2452 if (!m_attributes.stencil)
 2453 attributes->setStencil(false);
 2454 if (m_drawingBuffer) {
 2455 // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(),
 2456 // but it makes its own determination of whether multisampling is supported.
 2457 attributes->setAntialias(m_drawingBuffer->multisample());
 2458 }
 2459 return attributes.release();
 2460}
 2461
 2462GC3Denum WebGLRenderingContextBase::getError()
 2463{
 2464 if (m_isPendingPolicyResolution)
 2465 return GraphicsContext3D::NO_ERROR;
 2466 return m_context->getError();
 2467}
 2468
 2469WebGLExtension* WebGLRenderingContextBase::getExtension(const String& name)
 2470{
 2471 if (isContextLostOrPending())
 2472 return nullptr;
 2473
 2474 if (equalIgnoringCase(name, "EXT_blend_minmax")
 2475 && m_context->getExtensions()->supports("GL_EXT_blend_minmax")) {
 2476 if (!m_extBlendMinMax) {
 2477 m_context->getExtensions()->ensureEnabled("GL_EXT_blend_minmax");
 2478 m_extBlendMinMax = std::make_unique<EXTBlendMinMax>(this);
 2479 }
 2480 return m_extBlendMinMax.get();
 2481 }
 2482 if (equalIgnoringCase(name, "EXT_sRGB")
 2483 && m_context->getExtensions()->supports("GL_EXT_sRGB")) {
 2484 if (!m_extsRGB) {
 2485 m_context->getExtensions()->ensureEnabled("GL_EXT_sRGB");
 2486 m_extsRGB = std::make_unique<EXTsRGB>(this);
 2487 }
 2488 return m_extsRGB.get();
 2489 }
 2490 if (equalIgnoringCase(name, "EXT_frag_depth")
 2491 && m_context->getExtensions()->supports("GL_EXT_frag_depth")) {
 2492 if (!m_extFragDepth) {
 2493 m_context->getExtensions()->ensureEnabled("GL_EXT_frag_depth");
 2494 m_extFragDepth = std::make_unique<EXTFragDepth>(this);
 2495 }
 2496 return m_extFragDepth.get();
 2497 }
 2498 if (equalIgnoringCase(name, "EXT_shader_texture_lod")
 2499 && (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))) {
 2500 if (!m_extShaderTextureLOD) {
 2501 m_context->getExtensions()->ensureEnabled("GL_EXT_shader_texture_lod");
 2502 m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(this);
 2503 }
 2504 return m_extShaderTextureLOD.get();
 2505 }
 2506 if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic")
 2507 && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
 2508 if (!m_extTextureFilterAnisotropic) {
 2509 m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
 2510 m_extTextureFilterAnisotropic = std::make_unique<EXTTextureFilterAnisotropic>(this);
 2511 }
 2512 return m_extTextureFilterAnisotropic.get();
 2513 }
 2514 if (equalIgnoringCase(name, "OES_standard_derivatives")
 2515 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
 2516 if (!m_oesStandardDerivatives) {
 2517 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
 2518 m_oesStandardDerivatives = std::make_unique<OESStandardDerivatives>(this);
 2519 }
 2520 return m_oesStandardDerivatives.get();
 2521 }
 2522 if (equalIgnoringCase(name, "OES_texture_float")
 2523 && m_context->getExtensions()->supports("GL_OES_texture_float")) {
 2524 if (!m_oesTextureFloat) {
 2525 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
 2526 m_oesTextureFloat = std::make_unique<OESTextureFloat>(this);
 2527 }
 2528 return m_oesTextureFloat.get();
 2529 }
 2530 if (equalIgnoringCase(name, "OES_texture_float_linear")
 2531 && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) {
 2532 if (!m_oesTextureFloatLinear) {
 2533 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear");
 2534 m_oesTextureFloatLinear = std::make_unique<OESTextureFloatLinear>(this);
 2535 }
 2536 return m_oesTextureFloatLinear.get();
 2537 }
 2538 if (equalIgnoringCase(name, "OES_texture_half_float")
 2539 && m_context->getExtensions()->supports("GL_OES_texture_half_float")) {
 2540 if (!m_oesTextureHalfFloat) {
 2541 m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float");
 2542 m_oesTextureHalfFloat = std::make_unique<OESTextureHalfFloat>(this);
 2543 }
 2544 return m_oesTextureHalfFloat.get();
 2545 }
 2546 if (equalIgnoringCase(name, "OES_texture_half_float_linear")
 2547 && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) {
 2548 if (!m_oesTextureHalfFloatLinear) {
 2549 m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear");
 2550 m_oesTextureHalfFloatLinear = std::make_unique<OESTextureHalfFloatLinear>(this);
 2551 }
 2552 return m_oesTextureHalfFloatLinear.get();
 2553 }
 2554 if (equalIgnoringCase(name, "OES_vertex_array_object")
 2555 && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
 2556 if (!m_oesVertexArrayObject) {
 2557 m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
 2558 m_oesVertexArrayObject = std::make_unique<OESVertexArrayObject>(this);
 2559 }
 2560 return m_oesVertexArrayObject.get();
 2561 }
 2562 if (equalIgnoringCase(name, "OES_element_index_uint")
 2563 && m_context->getExtensions()->supports("GL_OES_element_index_uint")) {
 2564 if (!m_oesElementIndexUint) {
 2565 m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint");
 2566 m_oesElementIndexUint = std::make_unique<OESElementIndexUint>(this);
 2567 }
 2568 return m_oesElementIndexUint.get();
 2569 }
 2570 if (equalIgnoringCase(name, "WEBGL_lose_context")) {
 2571 if (!m_webglLoseContext)
 2572 m_webglLoseContext = std::make_unique<WebGLLoseContext>(this);
 2573 return m_webglLoseContext.get();
 2574 }
 2575 if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_atc"))
 2576 && WebGLCompressedTextureATC::supported(this)) {
 2577 if (!m_webglCompressedTextureATC)
 2578 m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(this);
 2579 return m_webglCompressedTextureATC.get();
 2580 }
 2581 if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc"))
 2582 && WebGLCompressedTexturePVRTC::supported(this)) {
 2583 if (!m_webglCompressedTexturePVRTC)
 2584 m_webglCompressedTexturePVRTC = std::make_unique<WebGLCompressedTexturePVRTC>(this);
 2585 return m_webglCompressedTexturePVRTC.get();
 2586 }
 2587 if (equalIgnoringCase(name, "WEBGL_compressed_texture_s3tc")
 2588 && WebGLCompressedTextureS3TC::supported(this)) {
 2589 if (!m_webglCompressedTextureS3TC)
 2590 m_webglCompressedTextureS3TC = std::make_unique<WebGLCompressedTextureS3TC>(this);
 2591 return m_webglCompressedTextureS3TC.get();
 2592 }
 2593 if (equalIgnoringCase(name, "WEBGL_depth_texture")
 2594 && WebGLDepthTexture::supported(graphicsContext3D())) {
 2595 if (!m_webglDepthTexture) {
 2596 m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
 2597 m_webglDepthTexture = std::make_unique<WebGLDepthTexture>(this);
 2598 }
 2599 return m_webglDepthTexture.get();
 2600 }
 2601 if (equalIgnoringCase(name, "WEBGL_draw_buffers") && supportsDrawBuffers()) {
 2602 if (!m_webglDrawBuffers) {
 2603 m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
 2604 m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(this);
 2605 }
 2606 return m_webglDrawBuffers.get();
 2607 }
 2608 if (equalIgnoringCase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) {
 2609 if (!m_angleInstancedArrays) {
 2610 m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays");
 2611 m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(this);
 2612 }
 2613 return m_angleInstancedArrays.get();
 2614 }
 2615 if (allowPrivilegedExtensions()) {
 2616 if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) {
 2617 if (!m_webglDebugRendererInfo)
 2618 m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(this);
 2619 return m_webglDebugRendererInfo.get();
 2620 }
 2621 if (equalIgnoringCase(name, "WEBGL_debug_shaders")
 2622 && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
 2623 if (!m_webglDebugShaders)
 2624 m_webglDebugShaders = std::make_unique<WebGLDebugShaders>(this);
 2625 return m_webglDebugShaders.get();
 2626 }
 2627 }
 2628
 2629 return nullptr;
 2630}
 2631
 2632WebGLGetInfo WebGLRenderingContextBase::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
 2633{
 2634 UNUSED_PARAM(ec);
 2635 if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
 2636 return WebGLGetInfo();
 2637
 2638 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
 2639 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
 2640 return WebGLGetInfo();
 2641 }
 2642
 2643 WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
 2644 if (!object) {
 2645 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
 2646 return WebGLGetInfo(GraphicsContext3D::NONE);
 2647 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
 2648 // specifies INVALID_OPERATION.
 2649 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
 2650 return WebGLGetInfo();
 2651 }
 2652
 2653 ASSERT(object->isTexture() || object->isRenderbuffer());
 2654 if (object->isTexture()) {
 2655 switch (pname) {
 2656 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
 2657 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
 2658 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
 2659 return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
 2660 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
 2661 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
 2662 case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
 2663 GC3Dint value = 0;
 2664 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
 2665 return WebGLGetInfo(value);
 2666 }
 2667 default:
 2668 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
 2669 return WebGLGetInfo();
 2670 }
 2671 } else {
 2672 switch (pname) {
 2673 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
 2674 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
 2675 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
 2676 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
 2677 case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
 2678 WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
 2679 GC3Denum renderBufferFormat = renderBuffer->getInternalFormat();
 2680 ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT);
 2681 if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT)
 2682 return WebGLGetInfo(Extensions3D::SRGB_EXT);
 2683 return WebGLGetInfo(GraphicsContext3D::LINEAR);
 2684 }
 2685 default:
 2686 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
 2687 return WebGLGetInfo();
 2688 }
 2689 }
 2690}
 2691
 2692WebGLGetInfo WebGLRenderingContextBase::getParameter(GC3Denum pname, ExceptionCode& ec)
 2693{
 2694 UNUSED_PARAM(ec);
 2695 if (isContextLostOrPending())
 2696 return WebGLGetInfo();
 2697 const int intZero = 0;
 2698 switch (pname) {
 2699 case GraphicsContext3D::ACTIVE_TEXTURE:
 2700 return getUnsignedIntParameter(pname);
 2701 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
 2702 return getWebGLFloatArrayParameter(pname);
 2703 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
 2704 return getWebGLFloatArrayParameter(pname);
 2705 case GraphicsContext3D::ALPHA_BITS:
 2706 return getIntParameter(pname);
 2707 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
 2708 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
 2709 case GraphicsContext3D::BLEND:
 2710 return getBooleanParameter(pname);
 2711 case GraphicsContext3D::BLEND_COLOR:
 2712 return getWebGLFloatArrayParameter(pname);
 2713 case GraphicsContext3D::BLEND_DST_ALPHA:
 2714 return getUnsignedIntParameter(pname);
 2715 case GraphicsContext3D::BLEND_DST_RGB:
 2716 return getUnsignedIntParameter(pname);
 2717 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
 2718 return getUnsignedIntParameter(pname);
 2719 case GraphicsContext3D::BLEND_EQUATION_RGB:
 2720 return getUnsignedIntParameter(pname);
 2721 case GraphicsContext3D::BLEND_SRC_ALPHA:
 2722 return getUnsignedIntParameter(pname);
 2723 case GraphicsContext3D::BLEND_SRC_RGB:
 2724 return getUnsignedIntParameter(pname);
 2725 case GraphicsContext3D::BLUE_BITS:
 2726 return getIntParameter(pname);
 2727 case GraphicsContext3D::COLOR_CLEAR_VALUE:
 2728 return getWebGLFloatArrayParameter(pname);
 2729 case GraphicsContext3D::COLOR_WRITEMASK:
 2730 return getBooleanArrayParameter(pname);
 2731 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
 2732 return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()));
 2733 case GraphicsContext3D::CULL_FACE:
 2734 return getBooleanParameter(pname);
 2735 case GraphicsContext3D::CULL_FACE_MODE:
 2736 return getUnsignedIntParameter(pname);
 2737 case GraphicsContext3D::CURRENT_PROGRAM:
 2738 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
 2739 case GraphicsContext3D::DEPTH_BITS:
 2740 if (!m_framebufferBinding && !m_attributes.depth)
 2741 return WebGLGetInfo(intZero);
 2742 return getIntParameter(pname);
 2743 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
 2744 return getFloatParameter(pname);
 2745 case GraphicsContext3D::DEPTH_FUNC:
 2746 return getUnsignedIntParameter(pname);
 2747 case GraphicsContext3D::DEPTH_RANGE:
 2748 return getWebGLFloatArrayParameter(pname);
 2749 case GraphicsContext3D::DEPTH_TEST:
 2750 return getBooleanParameter(pname);
 2751 case GraphicsContext3D::DEPTH_WRITEMASK:
 2752 return getBooleanParameter(pname);
 2753 case GraphicsContext3D::DITHER:
 2754 return getBooleanParameter(pname);
 2755 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
 2756 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
 2757 case GraphicsContext3D::FRAMEBUFFER_BINDING:
 2758 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
 2759 case GraphicsContext3D::FRONT_FACE:
 2760 return getUnsignedIntParameter(pname);
 2761 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
 2762 return getUnsignedIntParameter(pname);
 2763 case GraphicsContext3D::GREEN_BITS:
 2764 return getIntParameter(pname);
 2765 case GraphicsContext3D::LINE_WIDTH:
 2766 return getFloatParameter(pname);
 2767 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
 2768 return getIntParameter(pname);
 2769 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
 2770 return getIntParameter(pname);
 2771 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
 2772 return getIntParameter(pname);
 2773 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
 2774 return getIntParameter(pname);
 2775 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
 2776 return getIntParameter(pname);
 2777 case GraphicsContext3D::MAX_TEXTURE_SIZE:
 2778 return getIntParameter(pname);
 2779 case GraphicsContext3D::MAX_VARYING_VECTORS:
 2780 return getIntParameter(pname);
 2781 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
 2782 return getIntParameter(pname);
 2783 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
 2784 return getIntParameter(pname);
 2785 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
 2786 return getIntParameter(pname);
 2787 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
 2788 return getWebGLIntArrayParameter(pname);
 2789 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
 2790 // FIXME: should we always return 0 for this?
 2791 return getIntParameter(pname);
 2792 case GraphicsContext3D::PACK_ALIGNMENT:
 2793 return getIntParameter(pname);
 2794 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
 2795 return getFloatParameter(pname);
 2796 case GraphicsContext3D::POLYGON_OFFSET_FILL:
 2797 return getBooleanParameter(pname);
 2798 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
 2799 return getFloatParameter(pname);
 2800 case GraphicsContext3D::RED_BITS:
 2801 return getIntParameter(pname);
 2802 case GraphicsContext3D::RENDERBUFFER_BINDING:
 2803 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
 2804 case GraphicsContext3D::RENDERER:
 2805 return WebGLGetInfo(String("WebKit WebGL"));
 2806 case GraphicsContext3D::SAMPLE_BUFFERS:
 2807 return getIntParameter(pname);
 2808 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
 2809 return getBooleanParameter(pname);
 2810 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
 2811 return getFloatParameter(pname);
 2812 case GraphicsContext3D::SAMPLES:
 2813 return getIntParameter(pname);
 2814 case GraphicsContext3D::SCISSOR_BOX:
 2815 return getWebGLIntArrayParameter(pname);
 2816 case GraphicsContext3D::SCISSOR_TEST:
 2817 return getBooleanParameter(pname);
 2818 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
 2819 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
 2820 case GraphicsContext3D::STENCIL_BACK_FAIL:
 2821 return getUnsignedIntParameter(pname);
 2822 case GraphicsContext3D::STENCIL_BACK_FUNC:
 2823 return getUnsignedIntParameter(pname);
 2824 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
 2825 return getUnsignedIntParameter(pname);
 2826 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
 2827 return getUnsignedIntParameter(pname);
 2828 case GraphicsContext3D::STENCIL_BACK_REF:
 2829 return getIntParameter(pname);
 2830 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
 2831 return getUnsignedIntParameter(pname);
 2832 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
 2833 return getUnsignedIntParameter(pname);
 2834 case GraphicsContext3D::STENCIL_BITS:
 2835 if (!m_framebufferBinding && !m_attributes.stencil)
 2836 return WebGLGetInfo(intZero);
 2837 return getIntParameter(pname);
 2838 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
 2839 return getIntParameter(pname);
 2840 case GraphicsContext3D::STENCIL_FAIL:
 2841 return getUnsignedIntParameter(pname);
 2842 case GraphicsContext3D::STENCIL_FUNC:
 2843 return getUnsignedIntParameter(pname);
 2844 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
 2845 return getUnsignedIntParameter(pname);
 2846 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
 2847 return getUnsignedIntParameter(pname);
 2848 case GraphicsContext3D::STENCIL_REF:
 2849 return getIntParameter(pname);
 2850 case GraphicsContext3D::STENCIL_TEST:
 2851 return getBooleanParameter(pname);
 2852 case GraphicsContext3D::STENCIL_VALUE_MASK:
 2853 return getUnsignedIntParameter(pname);
 2854 case GraphicsContext3D::STENCIL_WRITEMASK:
 2855 return getUnsignedIntParameter(pname);
 2856 case GraphicsContext3D::SUBPIXEL_BITS:
 2857 return getIntParameter(pname);
 2858 case GraphicsContext3D::TEXTURE_BINDING_2D:
 2859 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding));
 2860 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
 2861 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding));
 2862 case GraphicsContext3D::UNPACK_ALIGNMENT:
 2863 return getIntParameter(pname);
 2864 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
 2865 return WebGLGetInfo(m_unpackFlipY);
 2866 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
 2867 return WebGLGetInfo(m_unpackPremultiplyAlpha);
 2868 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
 2869 return WebGLGetInfo(m_unpackColorspaceConversion);
 2870 case GraphicsContext3D::VENDOR:
 2871 return WebGLGetInfo(String("WebKit"));
 2872 case GraphicsContext3D::VERSION:
 2873 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
 2874 case GraphicsContext3D::VIEWPORT:
 2875 return getWebGLIntArrayParameter(pname);
 2876 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
 2877 if (m_oesStandardDerivatives)
 2878 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
 2879 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
 2880 return WebGLGetInfo();
 2881 case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
 2882 if (m_webglDebugRendererInfo)
 2883 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
 2884 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
 2885 return WebGLGetInfo();
 2886 case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
 2887 if (m_webglDebugRendererInfo)
 2888 return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
 2889 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
 2890 return WebGLGetInfo();
 2891 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
 2892 if (m_oesVertexArrayObject) {
 2893 if (!m_boundVertexArrayObject->isDefaultObject())
 2894 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
 2895 return WebGLGetInfo();
 2896 }
 2897 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
 2898 return WebGLGetInfo();
 2899 case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
 2900 if (m_extTextureFilterAnisotropic)
 2901 return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
 2902 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
 2903 return WebGLGetInfo();
 2904 case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
 2905 if (m_webglDrawBuffers)
 2906 return WebGLGetInfo(getMaxColorAttachments());
 2907 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
 2908 return WebGLGetInfo();
 2909 case Extensions3D::MAX_DRAW_BUFFERS_EXT:
 2910 if (m_webglDrawBuffers)
 2911 return WebGLGetInfo(getMaxDrawBuffers());
 2912 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
 2913 return WebGLGetInfo();
 2914 default:
 2915 if (m_webglDrawBuffers
 2916 && pname >= Extensions3D::DRAW_BUFFER0_EXT
 2917 && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
 2918 GC3Dint value = GraphicsContext3D::NONE;
 2919 if (m_framebufferBinding)
 2920 value = m_framebufferBinding->getDrawBuffer(pname);
 2921 else // emulated backbuffer
 2922 value = m_backDrawBuffer;
 2923 return WebGLGetInfo(value);
 2924 }
 2925 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
 2926 return WebGLGetInfo();
 2927 }
 2928}
 2929
 2930WebGLGetInfo WebGLRenderingContextBase::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
 2931{
 2932 UNUSED_PARAM(ec);
 2933 if (isContextLostOrPending() || !validateWebGLObject("getProgramParameter", program))
 2934 return WebGLGetInfo();
 2935
 2936 GC3Dint value = 0;
 2937 switch (pname) {
 2938 case GraphicsContext3D::DELETE_STATUS:
 2939 return WebGLGetInfo(program->isDeleted());
 2940 case GraphicsContext3D::VALIDATE_STATUS:
 2941 m_context->getProgramiv(objectOrZero(program), pname, &value);
 2942 return WebGLGetInfo(static_cast<bool>(value));
 2943 case GraphicsContext3D::LINK_STATUS:
 2944 return WebGLGetInfo(program->getLinkStatus());
 2945 case GraphicsContext3D::ATTACHED_SHADERS:
 2946 m_context->getProgramiv(objectOrZero(program), pname, &value);
 2947 return WebGLGetInfo(value);
 2948 case GraphicsContext3D::ACTIVE_ATTRIBUTES:
 2949 case GraphicsContext3D::ACTIVE_UNIFORMS:
 2950 m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), pname, &value);
 2951 return WebGLGetInfo(value);
 2952 default:
 2953 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name");
 2954 return WebGLGetInfo();
 2955 }
 2956}
 2957
 2958String WebGLRenderingContextBase::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
 2959{
 2960 UNUSED_PARAM(ec);
 2961 if (isContextLostOrPending())
 2962 return String();
 2963 if (!validateWebGLObject("getProgramInfoLog", program))
 2964 return "";
 2965 return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
 2966}
 2967
 2968WebGLGetInfo WebGLRenderingContextBase::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
 2969{
 2970 UNUSED_PARAM(ec);
 2971 if (isContextLostOrPending())
 2972 return WebGLGetInfo();
 2973 if (target != GraphicsContext3D::RENDERBUFFER) {
 2974 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target");
 2975 return WebGLGetInfo();
 2976 }
 2977 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
 2978 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound");
 2979 return WebGLGetInfo();
 2980 }
 2981
 2982 if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
 2983 && !m_renderbufferBinding->isValid()) {
 2984 ASSERT(!isDepthStencilSupported());
 2985 int value = 0;
 2986 switch (pname) {
 2987 case GraphicsContext3D::RENDERBUFFER_WIDTH:
 2988 value = m_renderbufferBinding->getWidth();
 2989 break;
 2990 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
 2991 value = m_renderbufferBinding->getHeight();
 2992 break;
 2993 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
 2994 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
 2995 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
 2996 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
 2997 value = 0;
 2998 break;
 2999 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
 3000 value = 24;
 3001 break;
 3002 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
 3003 value = 8;
 3004 break;
 3005 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
 3006 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
 3007 default:
 3008 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
 3009 return WebGLGetInfo();
 3010 }
 3011 return WebGLGetInfo(value);
 3012 }
 3013
 3014 GC3Dint value = 0;
 3015 switch (pname) {
 3016 case GraphicsContext3D::RENDERBUFFER_WIDTH:
 3017 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
 3018 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
 3019 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
 3020 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
 3021 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
 3022 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
 3023 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
 3024 m_context->getRenderbufferParameteriv(target, pname, &value);
 3025 return WebGLGetInfo(value);
 3026 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
 3027 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
 3028 default:
 3029 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
 3030 return WebGLGetInfo();
 3031 }
 3032}
 3033
 3034WebGLGetInfo WebGLRenderingContextBase::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
 3035{
 3036 UNUSED_PARAM(ec);
 3037 if (isContextLostOrPending() || !validateWebGLObject("getShaderParameter", shader))
 3038 return WebGLGetInfo();
 3039 GC3Dint value = 0;
 3040 switch (pname) {
 3041 case GraphicsContext3D::DELETE_STATUS:
 3042 return WebGLGetInfo(shader->isDeleted());
 3043 case GraphicsContext3D::COMPILE_STATUS:
 3044 m_context->getShaderiv(objectOrZero(shader), pname, &value);
 3045 return WebGLGetInfo(static_cast<bool>(value));
 3046 case GraphicsContext3D::SHADER_TYPE:
 3047 m_context->getShaderiv(objectOrZero(shader), pname, &value);
 3048 return WebGLGetInfo(static_cast<unsigned>(value));
 3049 default:
 3050 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
 3051 return WebGLGetInfo();
 3052 }
 3053}
 3054
 3055String WebGLRenderingContextBase::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
 3056{
 3057 UNUSED_PARAM(ec);
 3058 if (isContextLostOrPending())
 3059 return String();
 3060 if (!validateWebGLObject("getShaderInfoLog", shader))
 3061 return "";
 3062 return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
 3063}
 3064
 3065PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContextBase::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec)
 3066{
 3067 UNUSED_PARAM(ec);
 3068 if (isContextLostOrPending())
 3069 return nullptr;
 3070 switch (shaderType) {
 3071 case GraphicsContext3D::VERTEX_SHADER:
 3072 case GraphicsContext3D::FRAGMENT_SHADER:
 3073 break;
 3074 default:
 3075 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type");
 3076 return nullptr;
 3077 }
 3078 switch (precisionType) {
 3079 case GraphicsContext3D::LOW_FLOAT:
 3080 case GraphicsContext3D::MEDIUM_FLOAT:
 3081 case GraphicsContext3D::HIGH_FLOAT:
 3082 case GraphicsContext3D::LOW_INT:
 3083 case GraphicsContext3D::MEDIUM_INT:
 3084 case GraphicsContext3D::HIGH_INT:
 3085 break;
 3086 default:
 3087 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type");
 3088 return nullptr;
 3089 }
 3090
 3091 GC3Dint range[2] = {0, 0};
 3092 GC3Dint precision = 0;
 3093 m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision);
 3094 return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
 3095}
 3096
 3097String WebGLRenderingContextBase::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
 3098{
 3099 UNUSED_PARAM(ec);
 3100 if (isContextLostOrPending())
 3101 return String();
 3102 if (!validateWebGLObject("getShaderSource", shader))
 3103 return "";
 3104 return ensureNotNull(shader->getSource());
 3105}
 3106
 3107Vector<String> WebGLRenderingContextBase::getSupportedExtensions()
 3108{
 3109 Vector<String> result;
 3110
 3111 if (m_isPendingPolicyResolution)
 3112 return result;
 3113
 3114 if (m_context->getExtensions()->supports("GL_EXT_blend_minmax"))
 3115 result.append("EXT_blend_minmax");
 3116 if (m_context->getExtensions()->supports("GL_EXT_sRGB"))
 3117 result.append("EXT_sRGB");
 3118 if (m_context->getExtensions()->supports("GL_EXT_frag_depth"))
 3119 result.append("EXT_frag_depth");
 3120 if (m_context->getExtensions()->supports("GL_OES_texture_float"))
 3121 result.append("OES_texture_float");
 3122 if (m_context->getExtensions()->supports("GL_OES_texture_float_linear"))
 3123 result.append("OES_texture_float_linear");
 3124 if (m_context->getExtensions()->supports("GL_OES_texture_half_float"))
 3125 result.append("OES_texture_half_float");
 3126 if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear"))
 3127 result.append("OES_texture_half_float_linear");
 3128 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
 3129 result.append("OES_standard_derivatives");
 3130 if (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))
 3131 result.append("EXT_shader_texture_lod");
 3132 if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
 3133 result.append("WEBKIT_EXT_texture_filter_anisotropic");
 3134 if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
 3135 result.append("OES_vertex_array_object");
 3136 if (m_context->getExtensions()->supports("GL_OES_element_index_uint"))
 3137 result.append("OES_element_index_uint");
 3138 result.append("WEBGL_lose_context");
 3139 if (WebGLCompressedTextureATC::supported(this))
 3140 result.append("WEBKIT_WEBGL_compressed_texture_atc");
 3141 if (WebGLCompressedTexturePVRTC::supported(this))
 3142 result.append("WEBKIT_WEBGL_compressed_texture_pvrtc");
 3143 if (WebGLCompressedTextureS3TC::supported(this))
 3144 result.append("WEBGL_compressed_texture_s3tc");
 3145 if (WebGLDepthTexture::supported(graphicsContext3D()))
 3146 result.append("WEBGL_depth_texture");
 3147 if (supportsDrawBuffers())
 3148 result.append("WEBGL_draw_buffers");
 3149 if (ANGLEInstancedArrays::supported(this))
 3150 result.append("ANGLE_instanced_arrays");
 3151
 3152 if (allowPrivilegedExtensions()) {
 3153 if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
 3154 result.append("WEBGL_debug_shaders");
 3155 result.append("WEBGL_debug_renderer_info");
 3156 }
 3157
 3158 return result;
 3159}
 3160
 3161WebGLGetInfo WebGLRenderingContextBase::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
 3162{
 3163 UNUSED_PARAM(ec);
 3164 if (isContextLostOrPending())
 3165 return WebGLGetInfo();
 3166 WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false);
 3167 if (!tex)
 3168 return WebGLGetInfo();
 3169 GC3Dint value = 0;
 3170 switch (pname) {
 3171 case GraphicsContext3D::TEXTURE_MAG_FILTER:
 3172 case GraphicsContext3D::TEXTURE_MIN_FILTER:
 3173 case GraphicsContext3D::TEXTURE_WRAP_S:
 3174 case GraphicsContext3D::TEXTURE_WRAP_T:
 3175 m_context->getTexParameteriv(target, pname, &value);
 3176 return WebGLGetInfo(static_cast<unsigned>(value));
 3177 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
 3178 if (m_extTextureFilterAnisotropic) {
 3179 m_context->getTexParameteriv(target, pname, &value);
 3180 return WebGLGetInfo(static_cast<unsigned>(value));
 3181 }
 3182 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
 3183 return WebGLGetInfo();
 3184 default:
 3185 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name");
 3186 return WebGLGetInfo();
 3187 }
 3188}
 3189
 3190WebGLGetInfo WebGLRenderingContextBase::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
 3191{
 3192 UNUSED_PARAM(ec);
 3193 if (isContextLostOrPending() || !validateWebGLObject("getUniform", program))
 3194 return WebGLGetInfo();
 3195 if (!uniformLocation || uniformLocation->program() != program) {
 3196 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program");
 3197 return WebGLGetInfo();
 3198 }
 3199 GC3Dint location = uniformLocation->location();
 3200
 3201 GC3Denum baseType;
 3202 unsigned length;
 3203 switch (uniformLocation->type()) {
 3204 case GraphicsContext3D::BOOL:
 3205 baseType = GraphicsContext3D::BOOL;
 3206 length = 1;
 3207 break;
 3208 case GraphicsContext3D::BOOL_VEC2:
 3209 baseType = GraphicsContext3D::BOOL;
 3210 length = 2;
 3211 break;
 3212 case GraphicsContext3D::BOOL_VEC3:
 3213 baseType = GraphicsContext3D::BOOL;
 3214 length = 3;
 3215 break;
 3216 case GraphicsContext3D::BOOL_VEC4:
 3217 baseType = GraphicsContext3D::BOOL;
 3218 length = 4;
 3219 break;
 3220 case GraphicsContext3D::INT:
 3221 baseType = GraphicsContext3D::INT;
 3222 length = 1;
 3223 break;
 3224 case GraphicsContext3D::INT_VEC2:
 3225 baseType = GraphicsContext3D::INT;
 3226 length = 2;
 3227 break;
 3228 case GraphicsContext3D::INT_VEC3:
 3229 baseType = GraphicsContext3D::INT;
 3230 length = 3;
 3231 break;
 3232 case GraphicsContext3D::INT_VEC4:
 3233 baseType = GraphicsContext3D::INT;
 3234 length = 4;
 3235 break;
 3236 case GraphicsContext3D::FLOAT:
 3237 baseType = GraphicsContext3D::FLOAT;
 3238 length = 1;
 3239 break;
 3240 case GraphicsContext3D::FLOAT_VEC2:
 3241 baseType = GraphicsContext3D::FLOAT;
 3242 length = 2;
 3243 break;
 3244 case GraphicsContext3D::FLOAT_VEC3:
 3245 baseType = GraphicsContext3D::FLOAT;
 3246 length = 3;
 3247 break;
 3248 case GraphicsContext3D::FLOAT_VEC4:
 3249 baseType = GraphicsContext3D::FLOAT;
 3250 length = 4;
 3251 break;
 3252 case GraphicsContext3D::FLOAT_MAT2:
 3253 baseType = GraphicsContext3D::FLOAT;
 3254 length = 4;
 3255 break;
 3256 case GraphicsContext3D::FLOAT_MAT3:
 3257 baseType = GraphicsContext3D::FLOAT;
 3258 length = 9;
 3259 break;
 3260 case GraphicsContext3D::FLOAT_MAT4:
 3261 baseType = GraphicsContext3D::FLOAT;
 3262 length = 16;
 3263 break;
 3264 case GraphicsContext3D::SAMPLER_2D:
 3265 case GraphicsContext3D::SAMPLER_CUBE:
 3266 baseType = GraphicsContext3D::INT;
 3267 length = 1;
 3268 break;
 3269 default:
 3270 // Can't handle this type
 3271 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type");
 3272 return WebGLGetInfo();
 3273 }
 3274 switch (baseType) {
 3275 case GraphicsContext3D::FLOAT: {
 3276 GC3Dfloat value[16] = {0};
 3277 if (m_isRobustnessEXTSupported)
 3278 m_context->getExtensions()->getnUniformfvEXT(objectOrZero(program), location, 16 * sizeof(GC3Dfloat), value);
 3279 else
 3280 m_context->getUniformfv(objectOrZero(program), location, value);
 3281 if (length == 1)
 3282 return WebGLGetInfo(value[0]);
 3283 return WebGLGetInfo(Float32Array::create(value, length));
 3284 }
 3285 case GraphicsContext3D::INT: {
 3286 GC3Dint value[4] = {0};
 3287 if (m_isRobustnessEXTSupported)
 3288 m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
 3289 else
 3290 m_context->getUniformiv(objectOrZero(program), location, value);
 3291 if (length == 1)
 3292 return WebGLGetInfo(value[0]);
 3293 return WebGLGetInfo(Int32Array::create(value, length));
 3294 }
 3295 case GraphicsContext3D::BOOL: {
 3296 GC3Dint value[4] = {0};
 3297 if (m_isRobustnessEXTSupported)
 3298 m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value);
 3299 else
 3300 m_context->getUniformiv(objectOrZero(program), location, value);
 3301 if (length > 1) {
 3302 bool boolValue[16] = {0};
 3303 for (unsigned j = 0; j < length; j++)
 3304 boolValue[j] = static_cast<bool>(value[j]);
 3305 return WebGLGetInfo(boolValue, length);
 3306 }
 3307 return WebGLGetInfo(static_cast<bool>(value[0]));
 3308 }
 3309 default:
 3310 notImplemented();
 3311 }
 3312
 3313 // If we get here, something went wrong in our unfortunately complex logic above
 3314 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error");
 3315 return WebGLGetInfo();
 3316}
 3317
 3318PassRefPtr<WebGLUniformLocation> WebGLRenderingContextBase::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
 3319{
 3320 UNUSED_PARAM(ec);
 3321 if (isContextLostOrPending() || !validateWebGLObject("getUniformLocation", program))
 3322 return nullptr;
 3323 if (!validateLocationLength("getUniformLocation", name))
 3324 return nullptr;
 3325 if (!validateString("getUniformLocation", name))
 3326 return nullptr;
 3327 if (isPrefixReserved(name))
 3328 return nullptr;
 3329 if (!program->getLinkStatus()) {
 3330 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked");
 3331 return nullptr;
 3332 }
 3333 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
 3334 if (uniformLocation == -1)
 3335 return nullptr;
 3336
 3337 GC3Dint activeUniforms = 0;
 3338 m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
 3339 for (GC3Dint i = 0; i < activeUniforms; i++) {
 3340 ActiveInfo info;
 3341 if (!m_context->getActiveUniform(objectOrZero(program), i, info))
 3342 return nullptr;
 3343 // Strip "[0]" from the name if it's an array.
 3344 if (info.name.endsWith("[0]"))
 3345 info.name = info.name.left(info.name.length() - 3);
 3346 // If it's an array, we need to iterate through each element, appending "[index]" to the name.
 3347 for (GC3Dint index = 0; index < info.size; ++index) {
 3348 String uniformName = info.name + "[" + String::number(index) + "]";
 3349
 3350 if (name == uniformName || name == info.name)
 3351 return WebGLUniformLocation::create(program, uniformLocation, info.type);
 3352 }
 3353 }
 3354 return nullptr;
 3355}
 3356
 3357WebGLGetInfo WebGLRenderingContextBase::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
 3358{
 3359 UNUSED_PARAM(ec);
 3360
 3361 if (isContextLostOrPending())
 3362 return WebGLGetInfo();
 3363
 3364 if (index >= m_maxVertexAttribs) {
 3365 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range");
 3366 return WebGLGetInfo();
 3367 }
 3368
 3369 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
 3370
 3371 if (m_angleInstancedArrays && pname == GraphicsContext3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE)
 3372 return WebGLGetInfo(state.divisor);
 3373
 3374 switch (pname) {
 3375 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
 3376 if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
 3377 || !state.bufferBinding
 3378 || !state.bufferBinding->object())
 3379 return WebGLGetInfo();
 3380 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
 3381 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
 3382 return WebGLGetInfo(state.enabled);
 3383 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
 3384 return WebGLGetInfo(state.normalized);
 3385 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
 3386 return WebGLGetInfo(state.size);
 3387 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
 3388 return WebGLGetInfo(state.originalStride);
 3389 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
 3390 return WebGLGetInfo(state.type);
 3391 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
 3392 return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
 3393 default:
 3394 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name");
 3395 return WebGLGetInfo();
 3396 }
 3397}
 3398
 3399long long WebGLRenderingContextBase::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
 3400{
 3401 if (isContextLostOrPending())
 3402 return 0;
 3403 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
 3404 return static_cast<long long>(result);
 3405}
 3406
 3407void WebGLRenderingContextBase::hint(GC3Denum target, GC3Denum mode)
 3408{
 3409 if (isContextLostOrPending())
 3410 return;
 3411 bool isValid = false;
 3412 switch (target) {
 3413 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
 3414 isValid = true;
 3415 break;
 3416 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
 3417 if (m_oesStandardDerivatives)
 3418 isValid = true;
 3419 break;
 3420 }
 3421 if (!isValid) {
 3422 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
 3423 return;
 3424 }
 3425 m_context->hint(target, mode);
 3426}
 3427
 3428GC3Dboolean WebGLRenderingContextBase::isBuffer(WebGLBuffer* buffer)
 3429{
 3430 if (!buffer || isContextLostOrPending())
 3431 return 0;
 3432
 3433 if (!buffer->hasEverBeenBound())
 3434 return 0;
 3435
 3436 return m_context->isBuffer(buffer->object());
 3437}
 3438
 3439bool WebGLRenderingContextBase::isContextLost() const
 3440{
 3441 return m_contextLost;
 3442}
 3443
 3444bool WebGLRenderingContextBase::isContextLostOrPending()
 3445{
 3446 if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) {
 3447 LOG(WebGL, "Context is being used. Attempt to resolve the policy.");
 3448 Document& document = canvas()->document().topDocument();
 3449 Page* page = document.page();
 3450 if (page && !document.url().isLocalFile())
 3451 page->mainFrame().loader().client().resolveWebGLPolicyForURL(document.url());
 3452 // FIXME: We don't currently do anything with the result from resolution. A more
 3453 // complete implementation might try to construct a real context, etc and proceed
 3454 // with normal operation.
 3455 // https://bugs.webkit.org/show_bug.cgi?id=129122
 3456 m_hasRequestedPolicyResolution = true;
 3457 }
 3458
 3459 return m_contextLost || m_isPendingPolicyResolution;
 3460}
 3461
 3462GC3Dboolean WebGLRenderingContextBase::isEnabled(GC3Denum cap)
 3463{
 3464 if (isContextLostOrPending() || !validateCapability("isEnabled", cap))
 3465 return 0;
 3466 if (cap == GraphicsContext3D::STENCIL_TEST)
 3467 return m_stencilEnabled;
 3468 return m_context->isEnabled(cap);
 3469}
 3470
 3471GC3Dboolean WebGLRenderingContextBase::isFramebuffer(WebGLFramebuffer* framebuffer)
 3472{
 3473 if (!framebuffer || isContextLostOrPending())
 3474 return 0;
 3475
 3476 if (!framebuffer->hasEverBeenBound())
 3477 return 0;
 3478
 3479 return m_context->isFramebuffer(framebuffer->object());
 3480}
 3481
 3482GC3Dboolean WebGLRenderingContextBase::isProgram(WebGLProgram* program)
 3483{
 3484 if (!program || isContextLostOrPending())
 3485 return 0;
 3486
 3487 return m_context->isProgram(program->object());
 3488}
 3489
 3490GC3Dboolean WebGLRenderingContextBase::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
 3491{
 3492 if (!renderbuffer || isContextLostOrPending())
 3493 return 0;
 3494
 3495 if (!renderbuffer->hasEverBeenBound())
 3496 return 0;
 3497
 3498 return m_context->isRenderbuffer(renderbuffer->object());
 3499}
 3500
 3501GC3Dboolean WebGLRenderingContextBase::isShader(WebGLShader* shader)
 3502{
 3503 if (!shader || isContextLostOrPending())
 3504 return 0;
 3505
 3506 return m_context->isShader(shader->object());
 3507}
 3508
 3509GC3Dboolean WebGLRenderingContextBase::isTexture(WebGLTexture* texture)
 3510{
 3511 if (!texture || isContextLostOrPending())
 3512 return 0;
 3513
 3514 if (!texture->hasEverBeenBound())
 3515 return 0;
 3516
 3517 return m_context->isTexture(texture->object());
 3518}
 3519
 3520void WebGLRenderingContextBase::lineWidth(GC3Dfloat width)
 3521{
 3522 if (isContextLostOrPending())
 3523 return;
 3524 m_context->lineWidth(width);
 3525}
 3526
 3527void WebGLRenderingContextBase::linkProgram(WebGLProgram* program, ExceptionCode& ec)
 3528{
 3529 UNUSED_PARAM(ec);
 3530 if (isContextLostOrPending() || !validateWebGLObject("linkProgram", program))
 3531 return;
 3532 if (!isGLES2Compliant()) {
 3533 WebGLShader* vertexShader = program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER);
 3534 WebGLShader* fragmentShader = program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER);
 3535 if (!vertexShader || !vertexShader->isValid() || !fragmentShader || !fragmentShader->isValid() || !m_context->precisionsMatch(objectOrZero(vertexShader), objectOrZero(fragmentShader)) || !m_context->checkVaryingsPacking(objectOrZero(vertexShader), objectOrZero(fragmentShader))) {
 3536 program->setLinkStatus(false);
 3537 return;
 3538 }
 3539 }
 3540
 3541 m_context->linkProgram(objectOrZero(program));
 3542 program->increaseLinkCount();
 3543}
 3544
 3545void WebGLRenderingContextBase::pixelStorei(GC3Denum pname, GC3Dint param)
 3546{
 3547 if (isContextLostOrPending())
 3548 return;
 3549 switch (pname) {
 3550 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
 3551 m_unpackFlipY = param;
 3552 break;
 3553 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
 3554 m_unpackPremultiplyAlpha = param;
 3555 break;
 3556 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
 3557 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
 3558 m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
 3559 else {
 3560 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
 3561 return;
 3562 }
 3563 break;
 3564 case GraphicsContext3D::PACK_ALIGNMENT:
 3565 case GraphicsContext3D::UNPACK_ALIGNMENT:
 3566 if (param == 1 || param == 2 || param == 4 || param == 8) {
 3567 if (pname == GraphicsContext3D::PACK_ALIGNMENT)
 3568 m_packAlignment = param;
 3569 else // GraphicsContext3D::UNPACK_ALIGNMENT:
 3570 m_unpackAlignment = param;
 3571 m_context->pixelStorei(pname, param);
 3572 } else {
 3573 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment");
 3574 return;
 3575 }
 3576 break;
 3577 default:
 3578 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name");
 3579 return;
 3580 }
 3581}
 3582
 3583void WebGLRenderingContextBase::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
 3584{
 3585 if (isContextLostOrPending())
 3586 return;
 3587 m_context->polygonOffset(factor, units);
 3588}
 3589
 3590void WebGLRenderingContextBase::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
 3591{
 3592 if (isContextLostOrPending())
 3593 return;
 3594 // Due to WebGL's same-origin restrictions, it is not possible to
 3595 // taint the origin using the WebGL API.
 3596 ASSERT(canvas()->originClean());
 3597 // Validate input parameters.
 3598 if (!pixels) {
 3599 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView");
 3600 return;
 3601 }
 3602 switch (format) {
 3603 case GraphicsContext3D::ALPHA:
 3604 case GraphicsContext3D::RGB:
 3605 case GraphicsContext3D::RGBA:
 3606 break;
 3607 default:
 3608 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
 3609 return;
 3610 }
 3611 switch (type) {
 3612 case GraphicsContext3D::UNSIGNED_BYTE:
 3613 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
 3614 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
 3615 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
 3616 break;
 3617 default:
 3618 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
 3619 return;
 3620 }
 3621 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
 3622 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
 3623 return;
 3624 }
 3625 // Validate array type against pixel type.
 3626 if (pixels->getType() != JSC::TypeUint8) {
 3627 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
 3628 return;
 3629 }
 3630 const char* reason = "framebuffer incomplete";
 3631 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
 3632 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
 3633 return;
 3634 }
 3635 // Calculate array size, taking into consideration of PACK_ALIGNMENT.
 3636 unsigned totalBytesRequired = 0;
 3637 unsigned padding = 0;
 3638 if (!m_isRobustnessEXTSupported) {
 3639 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
 3640 if (error != GraphicsContext3D::NO_ERROR) {
 3641 synthesizeGLError(error, "readPixels", "invalid dimensions");
 3642 return;
 3643 }
 3644 if (pixels->byteLength() < totalBytesRequired) {
 3645 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
 3646 return;
 3647 }
 3648 }
 3649
 3650 clearIfComposited();
 3651 void* data = pixels->baseAddress();
 3652
 3653 {
 3654 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
 3655 if (m_isRobustnessEXTSupported)
 3656 m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels->byteLength(), data);
 3657 else
 3658 m_context->readPixels(x, y, width, height, format, type, data);
 3659 }
 3660
 3661#if OS(DARWIN)
 3662 if (m_isRobustnessEXTSupported) // we haven't computed padding
 3663 m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
 3664 // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
 3665 // on QC is fixed, i.e., when alpha is off, readPixels should
 3666 // set alpha to 255 instead of 0.
 3667 if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
 3668 unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
 3669 for (GC3Dsizei iy = 0; iy < height; ++iy) {
 3670 for (GC3Dsizei ix = 0; ix < width; ++ix) {
 3671 pixels[3] = 255;
 3672 pixels += 4;
 3673 }
 3674 pixels += padding;
 3675 }
 3676 }
 3677#endif
 3678}
 3679
 3680void WebGLRenderingContextBase::releaseShaderCompiler()
 3681{
 3682 if (isContextLostOrPending())
 3683 return;
 3684 m_context->releaseShaderCompiler();
 3685}
 3686
 3687void WebGLRenderingContextBase::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
 3688{
 3689 if (isContextLostOrPending())
 3690 return;
 3691 if (target != GraphicsContext3D::RENDERBUFFER) {
 3692 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
 3693 return;
 3694 }
 3695 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
 3696 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
 3697 return;
 3698 }
 3699 if (!validateSize("renderbufferStorage", width, height))
 3700 return;
 3701 switch (internalformat) {
 3702 case GraphicsContext3D::DEPTH_COMPONENT16:
 3703 case GraphicsContext3D::RGBA4:
 3704 case GraphicsContext3D::RGB5_A1:
 3705 case GraphicsContext3D::RGB565:
 3706 case GraphicsContext3D::STENCIL_INDEX8:
 3707 case Extensions3D::SRGB8_ALPHA8_EXT:
 3708 if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) {
 3709 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
 3710 return;
 3711 }
 3712 m_context->renderbufferStorage(target, internalformat, width, height);
 3713 m_renderbufferBinding->setInternalFormat(internalformat);
 3714 m_renderbufferBinding->setIsValid(true);
 3715 m_renderbufferBinding->setSize(width, height);
 3716 break;
 3717 case GraphicsContext3D::DEPTH_STENCIL:
 3718 if (isDepthStencilSupported())
 3719 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
 3720 m_renderbufferBinding->setSize(width, height);
 3721 m_renderbufferBinding->setIsValid(isDepthStencilSupported());
 3722 m_renderbufferBinding->setInternalFormat(internalformat);
 3723 break;
 3724 default:
 3725 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
 3726 return;
 3727 }
 3728 applyStencilTest();
 3729}
 3730
 3731void WebGLRenderingContextBase::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
 3732{
 3733 if (isContextLostOrPending())
 3734 return;
 3735 m_context->sampleCoverage(value, invert);
 3736}
 3737
 3738void WebGLRenderingContextBase::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 3739{
 3740 if (isContextLostOrPending())
 3741 return;
 3742 if (!validateSize("scissor", width, height))
 3743 return;
 3744 m_context->scissor(x, y, width, height);
 3745}
 3746
 3747void WebGLRenderingContextBase::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
 3748{
 3749 UNUSED_PARAM(ec);
 3750 if (isContextLostOrPending() || !validateWebGLObject("shaderSource", shader))
 3751 return;
 3752 String stringWithoutComments = StripComments(string).result();
 3753 if (!validateString("shaderSource", stringWithoutComments))
 3754 return;
 3755 shader->setSource(string);
 3756 m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
 3757}
 3758
 3759void WebGLRenderingContextBase::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
 3760{
 3761 if (isContextLostOrPending())
 3762 return;
 3763 if (!validateStencilFunc("stencilFunc", func))
 3764 return;
 3765 m_stencilFuncRef = ref;
 3766 m_stencilFuncRefBack = ref;
 3767 m_stencilFuncMask = mask;
 3768 m_stencilFuncMaskBack = mask;
 3769 m_context->stencilFunc(func, ref, mask);
 3770}
 3771
 3772void WebGLRenderingContextBase::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
 3773{
 3774 if (isContextLostOrPending())
 3775 return;
 3776 if (!validateStencilFunc("stencilFuncSeparate", func))
 3777 return;
 3778 switch (face) {
 3779 case GraphicsContext3D::FRONT_AND_BACK:
 3780 m_stencilFuncRef = ref;
 3781 m_stencilFuncRefBack = ref;
 3782 m_stencilFuncMask = mask;
 3783 m_stencilFuncMaskBack = mask;
 3784 break;
 3785 case GraphicsContext3D::FRONT:
 3786 m_stencilFuncRef = ref;
 3787 m_stencilFuncMask = mask;
 3788 break;
 3789 case GraphicsContext3D::BACK:
 3790 m_stencilFuncRefBack = ref;
 3791 m_stencilFuncMaskBack = mask;
 3792 break;
 3793 default:
 3794 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face");
 3795 return;
 3796 }
 3797 m_context->stencilFuncSeparate(face, func, ref, mask);
 3798}
 3799
 3800void WebGLRenderingContextBase::stencilMask(GC3Duint mask)
 3801{
 3802 if (isContextLostOrPending())
 3803 return;
 3804 m_stencilMask = mask;
 3805 m_stencilMaskBack = mask;
 3806 m_context->stencilMask(mask);
 3807}
 3808
 3809void WebGLRenderingContextBase::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
 3810{
 3811 if (isContextLostOrPending())
 3812 return;
 3813 switch (face) {
 3814 case GraphicsContext3D::FRONT_AND_BACK:
 3815 m_stencilMask = mask;
 3816 m_stencilMaskBack = mask;
 3817 break;
 3818 case GraphicsContext3D::FRONT:
 3819 m_stencilMask = mask;
 3820 break;
 3821 case GraphicsContext3D::BACK:
 3822 m_stencilMaskBack = mask;
 3823 break;
 3824 default:
 3825 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face");
 3826 return;
 3827 }
 3828 m_context->stencilMaskSeparate(face, mask);
 3829}
 3830
 3831void WebGLRenderingContextBase::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
 3832{
 3833 if (isContextLostOrPending())
 3834 return;
 3835 m_context->stencilOp(fail, zfail, zpass);
 3836}
 3837
 3838void WebGLRenderingContextBase::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
 3839{
 3840 if (isContextLostOrPending())
 3841 return;
 3842 m_context->stencilOpSeparate(face, fail, zfail, zpass);
 3843}
 3844
 3845void WebGLRenderingContextBase::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
 3846{
 3847 // FIXME: For now we ignore any errors returned.
 3848 ec = 0;
 3849 WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
 3850 ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type));
 3851 ASSERT(tex);
 3852 ASSERT(!level || !WebGLTexture::isNPOT(width, height));
 3853 if (!pixels) {
 3854 // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true.
 3855 // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures
 3856 // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
 3857 // clear.
 3858 if (isResourceSafe())
 3859 m_context->texImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
 3860 else {
 3861 bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
 3862 border, format, type, m_unpackAlignment);
 3863 if (!succeed)
 3864 return;
 3865 }
 3866 } else {
 3867 ASSERT(validateSettableTexFormat("texImage2D", internalformat));
 3868 m_context->moveErrorsToSyntheticErrorList();
 3869 m_context->texImage2D(target, level, internalformat, width, height,
 3870 border, format, type, pixels);
 3871 if (m_context->moveErrorsToSyntheticErrorList()) {
 3872 // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
 3873 tex->markInvalid(target, level);
 3874 return;
 3875 }
 3876 }
 3877 tex->setLevelInfo(target, level, internalformat, width, height, type);
 3878}
 3879
 3880void WebGLRenderingContextBase::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
 3881{
 3882 ec = 0;
 3883 Vector<uint8_t> data;
 3884 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
 3885 if (!imageExtractor.extractSucceeded()) {
 3886 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
 3887 return;
 3888 }
 3889 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
 3890 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
 3891 const void* imagePixelData = imageExtractor.imagePixelData();
 3892
 3893 bool needConversion = true;
 3894 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
 3895 needConversion = false;
 3896 else {
 3897 if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
 3898 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error");
 3899 return;
 3900 }
 3901 }
 3902
 3903 if (m_unpackAlignment != 1)
 3904 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 3905 texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, ec);
 3906 if (m_unpackAlignment != 1)
 3907 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 3908}
 3909
 3910bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset)
 3911{
 3912 if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type))
 3913 return false;
 3914
 3915 WebGLTexture* texture = validateTextureBinding(functionName, target, true);
 3916 if (!texture)
 3917 return false;
 3918
 3919 if (functionType == NotTexSubImage2D) {
 3920 if (level && WebGLTexture::isNPOT(width, height)) {
 3921 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2");
 3922 return false;
 3923 }
 3924 // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
 3925 // by checking if the ArrayBufferView is null or not.
 3926 if (sourceType != SourceArrayBufferView) {
 3927 if (!validateSettableTexFormat(functionName, format))
 3928 return false;
 3929 }
 3930 } else {
 3931 if (!validateSettableTexFormat(functionName, format))
 3932 return false;
 3933 if (!validateSize(functionName, xoffset, yoffset))
 3934 return false;
 3935 // Before checking if it is in the range, check if overflow happens first.
 3936 if (xoffset + width < 0 || yoffset + height < 0) {
 3937 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "bad dimensions");
 3938 return false;
 3939 }
 3940 if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) {
 3941 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
 3942 return false;
 3943 }
 3944 if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) {
 3945 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
 3946 return false;
 3947 }
 3948 }
 3949
 3950 return true;
 3951}
 3952
 3953void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 3954 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 3955 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
 3956{
 3957 if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed)
 3958 || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
 3959 return;
 3960 void* data = pixels ? pixels->baseAddress() : 0;
 3961 Vector<uint8_t> tempData;
 3962 bool changeUnpackAlignment = false;
 3963 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
 3964 if (!m_context->extractTextureData(width, height, format, type,
 3965 m_unpackAlignment,
 3966 m_unpackFlipY, m_unpackPremultiplyAlpha,
 3967 data,
 3968 tempData))
 3969 return;
 3970 data = tempData.data();
 3971 changeUnpackAlignment = true;
 3972 }
 3973 if (changeUnpackAlignment)
 3974 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 3975 texImage2DBase(target, level, internalformat, width, height, border,
 3976 format, type, data, ec);
 3977 if (changeUnpackAlignment)
 3978 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 3979}
 3980
 3981void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 3982 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
 3983{
 3984 ec = 0;
 3985 if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
 3986 return;
 3987 Vector<uint8_t> data;
 3988 bool needConversion = true;
 3989 // The data from ImageData is always of format RGBA8.
 3990 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
 3991 if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
 3992 needConversion = false;
 3993 else {
 3994 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
 3995 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
 3996 return;
 3997 }
 3998 }
 3999 if (m_unpackAlignment != 1)
 4000 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4001 texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
 4002 if (m_unpackAlignment != 1)
 4003 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4004}
 4005
 4006PassRefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(Image* image, int width, int height, int deviceScaleFactor)
 4007{
 4008 IntSize size(width, height);
 4009 size.scale(deviceScaleFactor);
 4010 ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
 4011 if (!buf) {
 4012 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
 4013 return nullptr;
 4014 }
 4015
 4016 FloatRect srcRect(FloatPoint(), image->size());
 4017 FloatRect destRect(FloatPoint(), size);
 4018 buf->context()->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect);
 4019 return buf->copyImage(ImageBuffer::fastCopyImageMode());
 4020}
 4021
 4022void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 4023 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
 4024{
 4025 ec = 0;
 4026 if (isContextLostOrPending() || !validateHTMLImageElement("texImage2D", image, ec))
 4027 return;
 4028
 4029 RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
 4030 if (imageForRender->isSVGImage())
 4031 imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
 4032
 4033 if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
 4034 return;
 4035
 4036 texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4037}
 4038
 4039void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 4040 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
 4041{
 4042 ec = 0;
 4043 if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
 4044 return;
 4045
 4046 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
 4047 // If possible, copy from the canvas element directly to the texture
 4048 // via the GPU, without a read-back to system memory.
 4049 //
 4050 // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when
 4051 // ImageBuffer::copyToPlatformTexture implementations are fully functional.
 4052 if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level)
 4053 && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) && type == GraphicsContext3D::UNSIGNED_BYTE) {
 4054 ImageBuffer* buffer = canvas->buffer();
 4055 if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
 4056 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
 4057 return;
 4058 }
 4059 }
 4060
 4061 RefPtr<ImageData> imageData = canvas->getImageData();
 4062 if (imageData)
 4063 texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
 4064 else
 4065 texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4066}
 4067
 4068#if ENABLE(VIDEO)
 4069PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy, ExceptionCode&)
 4070{
 4071 IntSize size(video->videoWidth(), video->videoHeight());
 4072 ImageBuffer* buf = m_generatedImageCache.imageBuffer(size);
 4073 if (!buf) {
 4074 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
 4075 return nullptr;
 4076 }
 4077 IntRect destRect(0, 0, size.width(), size.height());
 4078 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
 4079 video->paintCurrentFrameInContext(buf->context(), destRect);
 4080 return buf->copyImage(backingStoreCopy);
 4081}
 4082
 4083void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 4084 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
 4085{
 4086 ec = 0;
 4087 if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video, ec)
 4088 || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
 4089 return;
 4090
 4091 // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
 4092 // Otherwise, it will fall back to the normal SW path.
 4093 // FIXME: The current restrictions require that format shoud be RGB or RGBA,
 4094 // type should be UNSIGNED_BYTE and level should be 0. It may be lifted in the future.
 4095 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
 4096 if (GraphicsContext3D::TEXTURE_2D == target && texture
 4097 && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
 4098 && type == GraphicsContext3D::UNSIGNED_BYTE
 4099 && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level))
 4100 && !level) {
 4101 if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
 4102 texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
 4103 return;
 4104 }
 4105 }
 4106
 4107 // Normal pure SW path.
 4108 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
 4109 if (!image)
 4110 return;
 4111 texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4112}
 4113#endif
 4114
 4115void WebGLRenderingContextBase::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
 4116{
 4117 if (isContextLostOrPending())
 4118 return;
 4119 WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
 4120 if (!tex)
 4121 return;
 4122 switch (pname) {
 4123 case GraphicsContext3D::TEXTURE_MIN_FILTER:
 4124 case GraphicsContext3D::TEXTURE_MAG_FILTER:
 4125 break;
 4126 case GraphicsContext3D::TEXTURE_WRAP_S:
 4127 case GraphicsContext3D::TEXTURE_WRAP_T:
 4128 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
 4129 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
 4130 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter");
 4131 return;
 4132 }
 4133 break;
 4134 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
 4135 if (!m_extTextureFilterAnisotropic) {
 4136 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled");
 4137 return;
 4138 }
 4139 break;
 4140 default:
 4141 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name");
 4142 return;
 4143 }
 4144 if (isFloat) {
 4145 tex->setParameterf(pname, paramf);
 4146 m_context->texParameterf(target, pname, paramf);
 4147 } else {
 4148 tex->setParameteri(pname, parami);
 4149 m_context->texParameteri(target, pname, parami);
 4150 }
 4151}
 4152
 4153void WebGLRenderingContextBase::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
 4154{
 4155 texParameter(target, pname, param, 0, true);
 4156}
 4157
 4158void WebGLRenderingContextBase::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
 4159{
 4160 texParameter(target, pname, 0, param, false);
 4161}
 4162
 4163void WebGLRenderingContextBase::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
 4164{
 4165 // FIXME: For now we ignore any errors returned
 4166 ec = 0;
 4167 ASSERT(!isContextLost());
 4168 ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type));
 4169 ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
 4170 ASSERT(validateSettableTexFormat("texSubImage2D", format));
 4171 WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
 4172 if (!tex) {
 4173 ASSERT_NOT_REACHED();
 4174 return;
 4175 }
 4176 ASSERT((xoffset + width) >= 0);
 4177 ASSERT((yoffset + height) >= 0);
 4178 ASSERT(tex->getWidth(target, level) >= (xoffset + width));
 4179 ASSERT(tex->getHeight(target, level) >= (yoffset + height));
 4180 ASSERT(tex->getInternalFormat(target, level) == format);
 4181 ASSERT(tex->getType(target, level) == type);
 4182 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 4183}
 4184
 4185void WebGLRenderingContextBase::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
 4186{
 4187 ec = 0;
 4188 Vector<uint8_t> data;
 4189 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
 4190 if (!imageExtractor.extractSucceeded()) {
 4191 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
 4192 return;
 4193 }
 4194 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
 4195 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
 4196 const void* imagePixelData = imageExtractor.imagePixelData();
 4197
 4198 bool needConversion = true;
 4199 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
 4200 needConversion = false;
 4201 else {
 4202 if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
 4203 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
 4204 return;
 4205 }
 4206 }
 4207
 4208 if (m_unpackAlignment != 1)
 4209 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4210 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, ec);
 4211 if (m_unpackAlignment != 1)
 4212 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4213}
 4214
 4215void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4216 GC3Dsizei width, GC3Dsizei height,
 4217 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
 4218{
 4219 if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed)
 4220 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
 4221 return;
 4222 void* data = pixels->baseAddress();
 4223 Vector<uint8_t> tempData;
 4224 bool changeUnpackAlignment = false;
 4225 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
 4226 if (!m_context->extractTextureData(width, height, format, type,
 4227 m_unpackAlignment,
 4228 m_unpackFlipY, m_unpackPremultiplyAlpha,
 4229 data,
 4230 tempData))
 4231 return;
 4232 data = tempData.data();
 4233 changeUnpackAlignment = true;
 4234 }
 4235 if (changeUnpackAlignment)
 4236 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4237 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
 4238 if (changeUnpackAlignment)
 4239 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4240}
 4241
 4242void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4243 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
 4244{
 4245 ec = 0;
 4246 if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
 4247 return;
 4248
 4249 Vector<uint8_t> data;
 4250 bool needConversion = true;
 4251 // The data from ImageData is always of format RGBA8.
 4252 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
 4253 if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
 4254 needConversion = false;
 4255 else {
 4256 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
 4257 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
 4258 return;
 4259 }
 4260 }
 4261 if (m_unpackAlignment != 1)
 4262 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
 4263 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
 4264 if (m_unpackAlignment != 1)
 4265 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 4266}
 4267
 4268void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4269 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
 4270{
 4271 ec = 0;
 4272 if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
 4273 return;
 4274
 4275 RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
 4276 if (imageForRender->isSVGImage())
 4277 imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
 4278
 4279 if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
 4280 return;
 4281
 4282 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4283}
 4284
 4285void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4286 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
 4287{
 4288 ec = 0;
 4289 if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
 4290 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
 4291 return;
 4292
 4293 RefPtr<ImageData> imageData = canvas->getImageData();
 4294 if (imageData)
 4295 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
 4296 else
 4297 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4298}
 4299
 4300#if ENABLE(VIDEO)
 4301void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 4302 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
 4303{
 4304 ec = 0;
 4305 if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
 4306 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
 4307 return;
 4308
 4309 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
 4310 if (!image)
 4311 return;
 4312 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 4313}
 4314#endif
 4315
 4316void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
 4317{
 4318 UNUSED_PARAM(ec);
 4319 if (isContextLostOrPending() || !location)
 4320 return;
 4321
 4322 if (location->program() != m_currentProgram) {
 4323 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program");
 4324 return;
 4325 }
 4326
 4327 m_context->uniform1f(location->location(), x);
 4328}
 4329
 4330void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4331{
 4332 UNUSED_PARAM(ec);
 4333 if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, 1))
 4334 return;
 4335
 4336 m_context->uniform1fv(location->location(), v->length(), v->data());
 4337}
 4338
 4339void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4340{
 4341 UNUSED_PARAM(ec);
 4342 if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, size, 1))
 4343 return;
 4344
 4345 m_context->uniform1fv(location->location(), size, v);
 4346}
 4347
 4348void WebGLRenderingContextBase::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
 4349{
 4350 UNUSED_PARAM(ec);
 4351 if (isContextLostOrPending() || !location)
 4352 return;
 4353
 4354 if (location->program() != m_currentProgram) {
 4355 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program");
 4356 return;
 4357 }
 4358
 4359 if ((location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) && x >= (int)m_textureUnits.size()) {
 4360 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1i", "invalid texture unit");
 4361 return;
 4362 }
 4363
 4364 m_context->uniform1i(location->location(), x);
 4365}
 4366
 4367void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4368{
 4369 UNUSED_PARAM(ec);
 4370 if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, 1))
 4371 return;
 4372
 4373 if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) {
 4374 for (unsigned i = 0; i < v->length(); ++i) {
 4375 if (v->data()[i] >= static_cast<int>(m_textureUnits.size())) {
 4376 LOG(WebGL, "Texture unit size=%zu, v[%d]=%d. Location type = %04X.", m_textureUnits.size(), i, v->data()[i], location->type());
 4377 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
 4378 return;
 4379 }
 4380 }
 4381 }
 4382
 4383 m_context->uniform1iv(location->location(), v->length(), v->data());
 4384}
 4385
 4386void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4387{
 4388 UNUSED_PARAM(ec);
 4389 if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, size, 1))
 4390 return;
 4391
 4392 if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) {
 4393 for (unsigned i = 0; i < static_cast<unsigned>(size); ++i) {
 4394 if (((GC3Dint*)v)[i] >= static_cast<int>(m_textureUnits.size())) {
 4395 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit");
 4396 return;
 4397 }
 4398 }
 4399 }
 4400
 4401 m_context->uniform1iv(location->location(), size, v);
 4402}
 4403
 4404void WebGLRenderingContextBase::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
 4405{
 4406 UNUSED_PARAM(ec);
 4407 if (isContextLostOrPending() || !location)
 4408 return;
 4409
 4410 if (location->program() != m_currentProgram) {
 4411 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program");
 4412 return;
 4413 }
 4414
 4415 m_context->uniform2f(location->location(), x, y);
 4416}
 4417
 4418void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4419{
 4420 UNUSED_PARAM(ec);
 4421 if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, 2))
 4422 return;
 4423
 4424 m_context->uniform2fv(location->location(), v->length() / 2, v->data());
 4425}
 4426
 4427void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4428{
 4429 UNUSED_PARAM(ec);
 4430 if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, size, 2))
 4431 return;
 4432
 4433 m_context->uniform2fv(location->location(), size / 2, v);
 4434}
 4435
 4436void WebGLRenderingContextBase::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
 4437{
 4438 UNUSED_PARAM(ec);
 4439 if (isContextLostOrPending() || !location)
 4440 return;
 4441
 4442 if (location->program() != m_currentProgram) {
 4443 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program");
 4444 return;
 4445 }
 4446
 4447 m_context->uniform2i(location->location(), x, y);
 4448}
 4449
 4450void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4451{
 4452 UNUSED_PARAM(ec);
 4453 if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, 2))
 4454 return;
 4455
 4456 m_context->uniform2iv(location->location(), v->length() / 2, v->data());
 4457}
 4458
 4459void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4460{
 4461 UNUSED_PARAM(ec);
 4462 if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, size, 2))
 4463 return;
 4464
 4465 m_context->uniform2iv(location->location(), size / 2, v);
 4466}
 4467
 4468void WebGLRenderingContextBase::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
 4469{
 4470 UNUSED_PARAM(ec);
 4471 if (isContextLostOrPending() || !location)
 4472 return;
 4473
 4474 if (location->program() != m_currentProgram) {
 4475 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program");
 4476 return;
 4477 }
 4478
 4479 m_context->uniform3f(location->location(), x, y, z);
 4480}
 4481
 4482void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4483{
 4484 UNUSED_PARAM(ec);
 4485 if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, 3))
 4486 return;
 4487
 4488 m_context->uniform3fv(location->location(), v->length() / 3, v->data());
 4489}
 4490
 4491void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4492{
 4493 UNUSED_PARAM(ec);
 4494 if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, size, 3))
 4495 return;
 4496
 4497 m_context->uniform3fv(location->location(), size / 3, v);
 4498}
 4499
 4500void WebGLRenderingContextBase::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
 4501{
 4502 UNUSED_PARAM(ec);
 4503 if (isContextLostOrPending() || !location)
 4504 return;
 4505
 4506 if (location->program() != m_currentProgram) {
 4507 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program");
 4508 return;
 4509 }
 4510
 4511 m_context->uniform3i(location->location(), x, y, z);
 4512}
 4513
 4514void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4515{
 4516 UNUSED_PARAM(ec);
 4517 if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, 3))
 4518 return;
 4519
 4520 m_context->uniform3iv(location->location(), v->length() / 3, v->data());
 4521}
 4522
 4523void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4524{
 4525 UNUSED_PARAM(ec);
 4526 if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, size, 3))
 4527 return;
 4528
 4529 m_context->uniform3iv(location->location(), size / 3, v);
 4530}
 4531
 4532void WebGLRenderingContextBase::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
 4533{
 4534 UNUSED_PARAM(ec);
 4535 if (isContextLostOrPending() || !location)
 4536 return;
 4537
 4538 if (location->program() != m_currentProgram) {
 4539 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program");
 4540 return;
 4541 }
 4542
 4543 m_context->uniform4f(location->location(), x, y, z, w);
 4544}
 4545
 4546void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
 4547{
 4548 UNUSED_PARAM(ec);
 4549 if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, 4))
 4550 return;
 4551
 4552 m_context->uniform4fv(location->location(), v->length() / 4, v->data());
 4553}
 4554
 4555void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4556{
 4557 UNUSED_PARAM(ec);
 4558 if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, size, 4))
 4559 return;
 4560
 4561 m_context->uniform4fv(location->location(), size / 4, v);
 4562}
 4563
 4564void WebGLRenderingContextBase::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
 4565{
 4566 UNUSED_PARAM(ec);
 4567 if (isContextLostOrPending() || !location)
 4568 return;
 4569
 4570 if (location->program() != m_currentProgram) {
 4571 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program");
 4572 return;
 4573 }
 4574
 4575 m_context->uniform4i(location->location(), x, y, z, w);
 4576}
 4577
 4578void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
 4579{
 4580 UNUSED_PARAM(ec);
 4581 if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, 4))
 4582 return;
 4583
 4584 m_context->uniform4iv(location->location(), v->length() / 4, v->data());
 4585}
 4586
 4587void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
 4588{
 4589 UNUSED_PARAM(ec);
 4590 if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, size, 4))
 4591 return;
 4592
 4593 m_context->uniform4iv(location->location(), size / 4, v);
 4594}
 4595
 4596void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
 4597{
 4598 UNUSED_PARAM(ec);
 4599 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
 4600 return;
 4601 m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data());
 4602}
 4603
 4604void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4605{
 4606 UNUSED_PARAM(ec);
 4607 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
 4608 return;
 4609 m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
 4610}
 4611
 4612void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
 4613{
 4614 UNUSED_PARAM(ec);
 4615 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
 4616 return;
 4617 m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data());
 4618}
 4619
 4620void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4621{
 4622 UNUSED_PARAM(ec);
 4623 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
 4624 return;
 4625 m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
 4626}
 4627
 4628void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
 4629{
 4630 UNUSED_PARAM(ec);
 4631 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
 4632 return;
 4633 m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data());
 4634}
 4635
 4636void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
 4637{
 4638 UNUSED_PARAM(ec);
 4639 if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
 4640 return;
 4641 m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
 4642}
 4643
 4644void WebGLRenderingContextBase::useProgram(WebGLProgram* program, ExceptionCode& ec)
 4645{
 4646 UNUSED_PARAM(ec);
 4647 bool deleted;
 4648 if (!checkObjectToBeBound("useProgram", program, deleted))
 4649 return;
 4650 if (deleted)
 4651 program = 0;
 4652 if (program && !program->getLinkStatus()) {
 4653 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid");
 4654 return;
 4655 }
 4656 if (m_currentProgram != program) {
 4657 if (m_currentProgram)
 4658 m_currentProgram->onDetached(graphicsContext3D());
 4659 m_currentProgram = program;
 4660 m_context->useProgram(objectOrZero(program));
 4661 if (program)
 4662 program->onAttached();
 4663 }
 4664}
 4665
 4666void WebGLRenderingContextBase::validateProgram(WebGLProgram* program, ExceptionCode& ec)
 4667{
 4668 UNUSED_PARAM(ec);
 4669 if (isContextLostOrPending() || !validateWebGLObject("validateProgram", program))
 4670 return;
 4671 m_context->validateProgram(objectOrZero(program));
 4672}
 4673
 4674void WebGLRenderingContextBase::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
 4675{
 4676 vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
 4677}
 4678
 4679void WebGLRenderingContextBase::vertexAttrib1fv(GC3Duint index, Float32Array* v)
 4680{
 4681 vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
 4682}
 4683
 4684void WebGLRenderingContextBase::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4685{
 4686 vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
 4687}
 4688
 4689void WebGLRenderingContextBase::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
 4690{
 4691 vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
 4692}
 4693
 4694void WebGLRenderingContextBase::vertexAttrib2fv(GC3Duint index, Float32Array* v)
 4695{
 4696 vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
 4697}
 4698
 4699void WebGLRenderingContextBase::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4700{
 4701 vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
 4702}
 4703
 4704void WebGLRenderingContextBase::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
 4705{
 4706 vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
 4707}
 4708
 4709void WebGLRenderingContextBase::vertexAttrib3fv(GC3Duint index, Float32Array* v)
 4710{
 4711 vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
 4712}
 4713
 4714void WebGLRenderingContextBase::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4715{
 4716 vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
 4717}
 4718
 4719void WebGLRenderingContextBase::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
 4720{
 4721 vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
 4722}
 4723
 4724void WebGLRenderingContextBase::vertexAttrib4fv(GC3Duint index, Float32Array* v)
 4725{
 4726 vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
 4727}
 4728
 4729void WebGLRenderingContextBase::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
 4730{
 4731 vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
 4732}
 4733
 4734void WebGLRenderingContextBase::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
 4735{
 4736 UNUSED_PARAM(ec);
 4737 if (isContextLostOrPending())
 4738 return;
 4739 switch (type) {
 4740 case GraphicsContext3D::BYTE:
 4741 case GraphicsContext3D::UNSIGNED_BYTE:
 4742 case GraphicsContext3D::SHORT:
 4743 case GraphicsContext3D::UNSIGNED_SHORT:
 4744 case GraphicsContext3D::FLOAT:
 4745 break;
 4746 default:
 4747 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
 4748 return;
 4749 }
 4750 if (index >= m_maxVertexAttribs) {
 4751 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range");
 4752 return;
 4753 }
 4754 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
 4755 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset");
 4756 return;
 4757 }
 4758 if (!m_boundArrayBuffer) {
 4759 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER");
 4760 return;
 4761 }
 4762 // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
 4763 unsigned typeSize = sizeInBytes(type);
 4764 if (!typeSize) {
 4765 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
 4766 return;
 4767 }
 4768 if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
 4769 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type");
 4770 return;
 4771 }
 4772 GC3Dsizei bytesPerElement = size * typeSize;
 4773
 4774 m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer);
 4775 m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
 4776}
 4777
 4778void WebGLRenderingContextBase::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 4779{
 4780 if (isContextLostOrPending())
 4781 return;
 4782 if (!validateSize("viewport", width, height))
 4783 return;
 4784 m_context->viewport(x, y, width, height);
 4785}
 4786
 4787void WebGLRenderingContextBase::forceLostContext(WebGLRenderingContextBase::LostContextMode mode)
 4788{
 4789 if (isContextLostOrPending()) {
 4790 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost");
 4791 return;
 4792 }
 4793
 4794 m_contextGroup->loseContextGroup(mode);
 4795}
 4796
 4797void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode)
 4798{
 4799 if (isContextLost())
 4800 return;
 4801
 4802 m_contextLost = true;
 4803 m_contextLostMode = mode;
 4804
 4805 if (mode == RealLostContext) {
 4806 // Inform the embedder that a lost context was received. In response, the embedder might
 4807 // decide to take action such as asking the user for permission to use WebGL again.
 4808 if (Frame* frame = canvas()->document().frame())
 4809 frame->loader().client().didLoseWebGLContext(m_context->getExtensions()->getGraphicsResetStatusARB());
 4810 }
 4811
 4812 detachAndRemoveAllObjects();
 4813
 4814 if (m_drawingBuffer) {
 4815 // Make absolutely sure we do not refer to an already-deleted texture or framebuffer.
 4816 m_drawingBuffer->setTexture2DBinding(0);
 4817 m_drawingBuffer->setFramebufferBinding(0);
 4818 }
 4819
 4820 // There is no direct way to clear errors from a GL implementation and
 4821 // looping until getError() becomes NO_ERROR might cause an infinite loop if
 4822 // the driver or context implementation had a bug. So, loop a reasonably
 4823 // large number of times to clear any existing errors.
 4824 for (int i = 0; i < 100; ++i) {
 4825 if (m_context->getError() == GraphicsContext3D::NO_ERROR)
 4826 break;
 4827 }
 4828 ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole;
 4829 synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost", display);
 4830
 4831 // Don't allow restoration unless the context lost event has both been
 4832 // dispatched and its default behavior prevented.
 4833 m_restoreAllowed = false;
 4834
 4835 // Always defer the dispatch of the context lost event, to implement
 4836 // the spec behavior of queueing a task.
 4837 m_dispatchContextLostEventTimer.startOneShot(0);
 4838}
 4839
 4840void WebGLRenderingContextBase::forceRestoreContext()
 4841{
 4842 if (!isContextLostOrPending()) {
 4843 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost");
 4844 return;
 4845 }
 4846
 4847 if (!m_restoreAllowed) {
 4848 if (m_contextLostMode == SyntheticLostContext)
 4849 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed");
 4850 return;
 4851 }
 4852
 4853 if (!m_restoreTimer.isActive())
 4854 m_restoreTimer.startOneShot(0);
 4855}
 4856
 4857PlatformLayer* WebGLRenderingContextBase::platformLayer() const
 4858{
 4859 return (!isContextLost() && !m_isPendingPolicyResolution) ? m_context->platformLayer() : 0;
 4860}
 4861
 4862void WebGLRenderingContextBase::removeSharedObject(WebGLSharedObject* object)
 4863{
 4864 if (m_isPendingPolicyResolution)
 4865 return;
 4866
 4867 m_contextGroup->removeObject(object);
 4868}
 4869
 4870void WebGLRenderingContextBase::addSharedObject(WebGLSharedObject* object)
 4871{
 4872 if (m_isPendingPolicyResolution)
 4873 return;
 4874
 4875 ASSERT(!isContextLost());
 4876 m_contextGroup->addObject(object);
 4877}
 4878
 4879void WebGLRenderingContextBase::removeContextObject(WebGLContextObject* object)
 4880{
 4881 if (m_isPendingPolicyResolution)
 4882 return;
 4883
 4884 m_contextObjects.remove(object);
 4885}
 4886
 4887void WebGLRenderingContextBase::addContextObject(WebGLContextObject* object)
 4888{
 4889 if (m_isPendingPolicyResolution)
 4890 return;
 4891
 4892 ASSERT(!isContextLost());
 4893 m_contextObjects.add(object);
 4894}
 4895
 4896void WebGLRenderingContextBase::detachAndRemoveAllObjects()
 4897{
 4898 if (m_isPendingPolicyResolution)
 4899 return;
 4900
 4901 while (m_contextObjects.size() > 0) {
 4902 HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
 4903 (*it)->detachContext();
 4904 }
 4905}
 4906
 4907bool WebGLRenderingContextBase::hasPendingActivity() const
 4908{
 4909 return false;
 4910}
 4911
 4912void WebGLRenderingContextBase::stop()
 4913{
 4914 if (!isContextLost() && !m_isPendingPolicyResolution) {
 4915 forceLostContext(SyntheticLostContext);
 4916 destroyGraphicsContext3D();
 4917 }
 4918}
 4919
 4920WebGLGetInfo WebGLRenderingContextBase::getBooleanParameter(GC3Denum pname)
 4921{
 4922 GC3Dboolean value = 0;
 4923 m_context->getBooleanv(pname, &value);
 4924 return WebGLGetInfo(static_cast<bool>(value));
 4925}
 4926
 4927WebGLGetInfo WebGLRenderingContextBase::getBooleanArrayParameter(GC3Denum pname)
 4928{
 4929 if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
 4930 notImplemented();
 4931 return WebGLGetInfo(0, 0);
 4932 }
 4933 GC3Dboolean value[4] = {0};
 4934 m_context->getBooleanv(pname, value);
 4935 bool boolValue[4];
 4936 for (int ii = 0; ii < 4; ++ii)
 4937 boolValue[ii] = static_cast<bool>(value[ii]);
 4938 return WebGLGetInfo(boolValue, 4);
 4939}
 4940
 4941WebGLGetInfo WebGLRenderingContextBase::getFloatParameter(GC3Denum pname)
 4942{
 4943 GC3Dfloat value = 0;
 4944 m_context->getFloatv(pname, &value);
 4945 return WebGLGetInfo(value);
 4946}
 4947
 4948WebGLGetInfo WebGLRenderingContextBase::getIntParameter(GC3Denum pname)
 4949{
 4950 GC3Dint value = 0;
 4951 m_context->getIntegerv(pname, &value);
 4952 return WebGLGetInfo(value);
 4953}
 4954
 4955WebGLGetInfo WebGLRenderingContextBase::getUnsignedIntParameter(GC3Denum pname)
 4956{
 4957 GC3Dint value = 0;
 4958 m_context->getIntegerv(pname, &value);
 4959 return WebGLGetInfo(static_cast<unsigned>(value));
 4960}
 4961
 4962WebGLGetInfo WebGLRenderingContextBase::getWebGLFloatArrayParameter(GC3Denum pname)
 4963{
 4964 GC3Dfloat value[4] = {0};
 4965 m_context->getFloatv(pname, value);
 4966 unsigned length = 0;
 4967 switch (pname) {
 4968 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
 4969 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
 4970 case GraphicsContext3D::DEPTH_RANGE:
 4971 length = 2;
 4972 break;
 4973 case GraphicsContext3D::BLEND_COLOR:
 4974 case GraphicsContext3D::COLOR_CLEAR_VALUE:
 4975 length = 4;
 4976 break;
 4977 default:
 4978 notImplemented();
 4979 }
 4980 return WebGLGetInfo(Float32Array::create(value, length));
 4981}
 4982
 4983WebGLGetInfo WebGLRenderingContextBase::getWebGLIntArrayParameter(GC3Denum pname)
 4984{
 4985 GC3Dint value[4] = {0};
 4986 m_context->getIntegerv(pname, value);
 4987 unsigned length = 0;
 4988 switch (pname) {
 4989 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
 4990 length = 2;
 4991 break;
 4992 case GraphicsContext3D::SCISSOR_BOX:
 4993 case GraphicsContext3D::VIEWPORT:
 4994 length = 4;
 4995 break;
 4996 default:
 4997 notImplemented();
 4998 }
 4999 return WebGLGetInfo(Int32Array::create(value, length));
 5000}
 5001
 5002void WebGLRenderingContextBase::checkTextureCompleteness(const char* functionName, bool prepareToDraw)
 5003{
 5004 bool resetActiveUnit = false;
 5005 WebGLTexture::TextureExtensionFlag extensions = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0));
 5006
 5007 for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
 5008 if ((m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
 5009 || (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))) {
 5010 if (ii != m_activeTextureUnit) {
 5011 m_context->activeTexture(ii);
 5012 resetActiveUnit = true;
 5013 } else if (resetActiveUnit) {
 5014 m_context->activeTexture(ii);
 5015 resetActiveUnit = false;
 5016 }
 5017 WebGLTexture* tex2D;
 5018 WebGLTexture* texCubeMap;
 5019 if (prepareToDraw) {
 5020 String msg(String("texture bound to texture unit ") + String::number(ii)
 5021 + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete',"
 5022 + " or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled.");
 5023 printGLWarningToConsole(functionName, msg.utf8().data());
 5024 tex2D = m_blackTexture2D.get();
 5025 texCubeMap = m_blackTextureCubeMap.get();
 5026 } else {
 5027 tex2D = m_textureUnits[ii].texture2DBinding.get();
 5028 texCubeMap = m_textureUnits[ii].textureCubeMapBinding.get();
 5029 }
 5030 if (m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions))
 5031 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
 5032 if (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))
 5033 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
 5034 }
 5035 }
 5036 if (resetActiveUnit)
 5037 m_context->activeTexture(m_activeTextureUnit);
 5038}
 5039
 5040void WebGLRenderingContextBase::createFallbackBlackTextures1x1()
 5041{
 5042 unsigned char black[] = {0, 0, 0, 255};
 5043 m_blackTexture2D = createTexture();
 5044 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
 5045 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
 5046 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5047 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
 5048 m_blackTextureCubeMap = createTexture();
 5049 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
 5050 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
 5051 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5052 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
 5053 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5054 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
 5055 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5056 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
 5057 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5058 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
 5059 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5060 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
 5061 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
 5062 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
 5063}
 5064
 5065bool WebGLRenderingContextBase::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, GC3Denum colorBufferFormat)
 5066{
 5067 unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
 5068 unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
 5069 return (need & have) == need;
 5070}
 5071
 5072GC3Denum WebGLRenderingContextBase::getBoundFramebufferColorFormat()
 5073{
 5074 if (m_framebufferBinding && m_framebufferBinding->object())
 5075 return m_framebufferBinding->getColorBufferFormat();
 5076 if (m_attributes.alpha)
 5077 return GraphicsContext3D::RGBA;
 5078 return GraphicsContext3D::RGB;
 5079}
 5080
 5081int WebGLRenderingContextBase::getBoundFramebufferWidth()
 5082{
 5083 if (m_framebufferBinding && m_framebufferBinding->object())
 5084 return m_framebufferBinding->getColorBufferWidth();
 5085 return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width();
 5086}
 5087
 5088int WebGLRenderingContextBase::getBoundFramebufferHeight()
 5089{
 5090 if (m_framebufferBinding && m_framebufferBinding->object())
 5091 return m_framebufferBinding->getColorBufferHeight();
 5092 return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height();
 5093}
 5094
 5095WebGLTexture* WebGLRenderingContextBase::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap)
 5096{
 5097 WebGLTexture* texture = nullptr;
 5098 switch (target) {
 5099 case GraphicsContext3D::TEXTURE_2D:
 5100 texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get();
 5101 break;
 5102 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
 5103 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
 5104 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
 5105 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
 5106 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
 5107 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
 5108 if (!useSixEnumsForCubeMap) {
 5109 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
 5110 return nullptr;
 5111 }
 5112 texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
 5113 break;
 5114 case GraphicsContext3D::TEXTURE_CUBE_MAP:
 5115 if (useSixEnumsForCubeMap) {
 5116 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
 5117 return nullptr;
 5118 }
 5119 texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get();
 5120 break;
 5121 default:
 5122 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
 5123 return nullptr;
 5124 }
 5125 if (!texture)
 5126 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture");
 5127 return texture;
 5128}
 5129
 5130bool WebGLRenderingContextBase::validateLocationLength(const char* functionName, const String& string)
 5131{
 5132 const unsigned maxWebGLLocationLength = 256;
 5133 if (string.length() > maxWebGLLocationLength) {
 5134 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256");
 5135 return false;
 5136 }
 5137 return true;
 5138}
 5139
 5140bool WebGLRenderingContextBase::validateSize(const char* functionName, GC3Dint x, GC3Dint y)
 5141{
 5142 if (x < 0 || y < 0) {
 5143 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
 5144 return false;
 5145 }
 5146 return true;
 5147}
 5148
 5149bool WebGLRenderingContextBase::validateString(const char* functionName, const String& string)
 5150{
 5151 for (size_t i = 0; i < string.length(); ++i) {
 5152 if (!validateCharacter(string[i])) {
 5153 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII");
 5154 return false;
 5155 }
 5156 }
 5157 return true;
 5158}
 5159
 5160bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
 5161{
 5162 switch (format) {
 5163 case GraphicsContext3D::ALPHA:
 5164 case GraphicsContext3D::LUMINANCE:
 5165 case GraphicsContext3D::LUMINANCE_ALPHA:
 5166 case GraphicsContext3D::RGB:
 5167 case GraphicsContext3D::RGBA:
 5168 break;
 5169 case GraphicsContext3D::DEPTH_STENCIL:
 5170 case GraphicsContext3D::DEPTH_COMPONENT:
 5171 if (m_webglDepthTexture)
 5172 break;
 5173 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
 5174 return false;
 5175 case Extensions3D::SRGB_EXT:
 5176 case Extensions3D::SRGB_ALPHA_EXT:
 5177 default:
 5178 if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
 5179 && m_extsRGB)
 5180 break;
 5181 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
 5182 return false;
 5183 }
 5184
 5185 switch (type) {
 5186 case GraphicsContext3D::UNSIGNED_BYTE:
 5187 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
 5188 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
 5189 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
 5190 break;
 5191 case GraphicsContext3D::FLOAT:
 5192 if (m_oesTextureFloat)
 5193 break;
 5194 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5195 return false;
 5196 case GraphicsContext3D::HALF_FLOAT_OES:
 5197 if (m_oesTextureHalfFloat)
 5198 break;
 5199 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5200 return false;
 5201 case GraphicsContext3D::UNSIGNED_INT:
 5202 case GraphicsContext3D::UNSIGNED_INT_24_8:
 5203 case GraphicsContext3D::UNSIGNED_SHORT:
 5204 if (m_webglDepthTexture)
 5205 break;
 5206 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5207 return false;
 5208 default:
 5209 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
 5210 return false;
 5211 }
 5212
 5213 // Verify that the combination of format and type is supported.
 5214 switch (format) {
 5215 case GraphicsContext3D::ALPHA:
 5216 case GraphicsContext3D::LUMINANCE:
 5217 case GraphicsContext3D::LUMINANCE_ALPHA:
 5218 if (type != GraphicsContext3D::UNSIGNED_BYTE
 5219 && type != GraphicsContext3D::FLOAT
 5220 && type != GraphicsContext3D::HALF_FLOAT_OES) {
 5221 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
 5222 return false;
 5223 }
 5224 break;
 5225 case GraphicsContext3D::RGB:
 5226 case Extensions3D::SRGB_EXT:
 5227 if (type != GraphicsContext3D::UNSIGNED_BYTE
 5228 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
 5229 && type != GraphicsContext3D::FLOAT
 5230 && type != GraphicsContext3D::HALF_FLOAT_OES) {
 5231 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
 5232 return false;
 5233 }
 5234 break;
 5235 case GraphicsContext3D::RGBA:
 5236 case Extensions3D::SRGB_ALPHA_EXT:
 5237 if (type != GraphicsContext3D::UNSIGNED_BYTE
 5238 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
 5239 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
 5240 && type != GraphicsContext3D::FLOAT
 5241 && type != GraphicsContext3D::HALF_FLOAT_OES) {
 5242 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
 5243 return false;
 5244 }
 5245 break;
 5246 case GraphicsContext3D::DEPTH_COMPONENT:
 5247 if (!m_webglDepthTexture) {
 5248 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
 5249 return false;
 5250 }
 5251 if (type != GraphicsContext3D::UNSIGNED_SHORT
 5252 && type != GraphicsContext3D::UNSIGNED_INT) {
 5253 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
 5254 return false;
 5255 }
 5256 if (level > 0) {
 5257 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
 5258 return false;
 5259 }
 5260 break;
 5261 case GraphicsContext3D::DEPTH_STENCIL:
 5262 if (!m_webglDepthTexture) {
 5263 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
 5264 return false;
 5265 }
 5266 if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
 5267 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
 5268 return false;
 5269 }
 5270 if (level > 0) {
 5271 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
 5272 return false;
 5273 }
 5274 break;
 5275 default:
 5276 ASSERT_NOT_REACHED();
 5277 }
 5278
 5279 return true;
 5280}
 5281
 5282bool WebGLRenderingContextBase::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
 5283{
 5284 if (level < 0) {
 5285 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
 5286 return false;
 5287 }
 5288 switch (target) {
 5289 case GraphicsContext3D::TEXTURE_2D:
 5290 if (level >= m_maxTextureLevel) {
 5291 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
 5292 return false;
 5293 }
 5294 break;
 5295 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
 5296 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
 5297 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
 5298 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
 5299 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
 5300 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
 5301 if (level >= m_maxCubeMapTextureLevel) {
 5302 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
 5303 return false;
 5304 }
 5305 break;
 5306 }
 5307 // This function only checks if level is legal, so we return true and don't
 5308 // generate INVALID_ENUM if target is illegal.
 5309 return true;
 5310}
 5311
 5312bool WebGLRenderingContextBase::validateTexFuncParameters(const char* functionName,
 5313 TexFuncValidationFunctionType functionType,
 5314 GC3Denum target, GC3Dint level,
 5315 GC3Denum internalformat,
 5316 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 5317 GC3Denum format, GC3Denum type)
 5318{
 5319 // We absolutely have to validate the format and type combination.
 5320 // The texImage2D entry points taking HTMLImage, etc. will produce
 5321 // temporary data based on this combination, so it must be legal.
 5322 if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
 5323 return false;
 5324
 5325 if (width < 0 || height < 0) {
 5326 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
 5327 return false;
 5328 }
 5329
 5330 GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
 5331 switch (target) {
 5332 case GraphicsContext3D::TEXTURE_2D:
 5333 if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
 5334 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
 5335 return false;
 5336 }
 5337 break;
 5338 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
 5339 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
 5340 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
 5341 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
 5342 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
 5343 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
 5344 if (functionType != TexSubImage2D && width != height) {
 5345 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
 5346 return false;
 5347 }
 5348 // No need to check height here. For texImage width == height.
 5349 // For texSubImage that will be checked when checking yoffset + height is in range.
 5350 if (width > maxTextureSizeForLevel) {
 5351 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
 5352 return false;
 5353 }
 5354 break;
 5355 default:
 5356 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
 5357 return false;
 5358 }
 5359
 5360 if (format != internalformat) {
 5361 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
 5362 return false;
 5363 }
 5364
 5365 if (border) {
 5366 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
 5367 return false;
 5368 }
 5369
 5370 return true;
 5371}
 5372
 5373bool WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GC3Dint level,
 5374 GC3Dsizei width, GC3Dsizei height,
 5375 GC3Denum format, GC3Denum type,
 5376 ArrayBufferView* pixels,
 5377 NullDisposition disposition)
 5378{
 5379 if (!pixels) {
 5380 if (disposition == NullAllowed)
 5381 return true;
 5382 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
 5383 return false;
 5384 }
 5385
 5386 if (!validateTexFuncFormatAndType(functionName, format, type, level))
 5387 return false;
 5388 if (!validateSettableTexFormat(functionName, format))
 5389 return false;
 5390
 5391 switch (type) {
 5392 case GraphicsContext3D::UNSIGNED_BYTE:
 5393 if (pixels->getType() != JSC::TypeUint8) {
 5394 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
 5395 return false;
 5396 }
 5397 break;
 5398 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
 5399 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
 5400 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
 5401 if (pixels->getType() != JSC::TypeUint16) {
 5402 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
 5403 return false;
 5404 }
 5405 break;
 5406 case GraphicsContext3D::FLOAT: // OES_texture_float
 5407 if (pixels->getType() != JSC::TypeFloat32) {
 5408 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
 5409 return false;
 5410 }
 5411 break;
 5412 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
 5413 // As per the specification, ArrayBufferView should be null when
 5414 // OES_texture_half_float is enabled.
 5415 if (pixels) {
 5416 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
 5417 return false;
 5418 }
 5419 break;
 5420 default:
 5421 ASSERT_NOT_REACHED();
 5422 }
 5423
 5424 unsigned totalBytesRequired;
 5425 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
 5426 if (error != GraphicsContext3D::NO_ERROR) {
 5427 synthesizeGLError(error, functionName, "invalid texture dimensions");
 5428 return false;
 5429 }
 5430 if (pixels->byteLength() < totalBytesRequired) {
 5431 if (m_unpackAlignment != 1) {
 5432 error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
 5433 if (pixels->byteLength() == totalBytesRequired) {
 5434 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
 5435 return false;
 5436 }
 5437 }
 5438 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
 5439 return false;
 5440 }
 5441 return true;
 5442}
 5443
 5444bool WebGLRenderingContextBase::validateCompressedTexFormat(GC3Denum format)
 5445{
 5446 return m_compressedTextureFormats.contains(format);
 5447}
 5448
 5449bool WebGLRenderingContextBase::validateCompressedTexFuncData(const char* functionName,
 5450 GC3Dsizei width, GC3Dsizei height,
 5451 GC3Denum format, ArrayBufferView* pixels)
 5452{
 5453 if (!pixels) {
 5454 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
 5455 return false;
 5456 }
 5457 if (width < 0 || height < 0) {
 5458 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
 5459 return false;
 5460 }
 5461
 5462 unsigned bytesRequired = 0;
 5463
 5464 switch (format) {
 5465 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
 5466 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
 5467 case Extensions3D::COMPRESSED_ATC_RGB_AMD:
 5468 {
 5469 const int kBlockSize = 8;
 5470 const int kBlockWidth = 4;
 5471 const int kBlockHeight = 4;
 5472 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
 5473 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
 5474 bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
 5475 }
 5476 break;
 5477 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
 5478 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
 5479 case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD:
 5480 case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
 5481 {
 5482 const int kBlockSize = 16;
 5483 const int kBlockWidth = 4;
 5484 const int kBlockHeight = 4;
 5485 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
 5486 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
 5487 bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize;
 5488 }
 5489 break;
 5490 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
 5491 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
 5492 {
 5493 const int kBlockSize = 8;
 5494 const int kBlockWidth = 8;
 5495 const int kBlockHeight = 8;
 5496 bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 4 + 7) / kBlockSize;
 5497 }
 5498 break;
 5499 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
 5500 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
 5501 {
 5502 const int kBlockSize = 8;
 5503 const int kBlockWidth = 16;
 5504 const int kBlockHeight = 8;
 5505 bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 2 + 7) / kBlockSize;
 5506 }
 5507 break;
 5508 default:
 5509 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format");
 5510 return false;
 5511 }
 5512
 5513 if (pixels->byteLength() != bytesRequired) {
 5514 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions");
 5515 return false;
 5516 }
 5517
 5518 return true;
 5519}
 5520
 5521bool WebGLRenderingContextBase::validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format)
 5522{
 5523 switch (format) {
 5524 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
 5525 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
 5526 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
 5527 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
 5528 const GC3Dsizei kBlockWidth = 4;
 5529 const GC3Dsizei kBlockHeight = 4;
 5530 const GC3Dint maxTextureSize = target ? m_maxTextureSize : m_maxCubeMapTextureSize;
 5531 const GC3Dsizei maxCompressedDimension = maxTextureSize >> level;
 5532 bool widthValid = (level && width == 1) || (level && width == 2) || (!(width % kBlockWidth) && width <= maxCompressedDimension);
 5533 bool heightValid = (level && height == 1) || (level && height == 2) || (!(height % kBlockHeight) && height <= maxCompressedDimension);
 5534 if (!widthValid || !heightValid) {
 5535 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
 5536 return false;
 5537 }
 5538 return true;
 5539 }
 5540 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
 5541 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
 5542 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
 5543 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
 5544 // Height and width must be powers of 2.
 5545 if ((width & (width - 1)) || (height & (height - 1))) {
 5546 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
 5547 return false;
 5548 }
 5549 return true;
 5550 default:
 5551 return false;
 5552 }
 5553}
 5554
 5555bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 5556 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
 5557{
 5558 if (xoffset < 0 || yoffset < 0) {
 5559 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
 5560 return false;
 5561 }
 5562
 5563 switch (format) {
 5564 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
 5565 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
 5566 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
 5567 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
 5568 const int kBlockWidth = 4;
 5569 const int kBlockHeight = 4;
 5570 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
 5571 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4");
 5572 return false;
 5573 }
 5574 if (width - xoffset > tex->getWidth(target, level)
 5575 || height - yoffset > tex->getHeight(target, level)) {
 5576 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range");
 5577 return false;
 5578 }
 5579 return validateCompressedTexDimensions(functionName, target, level, width, height, format);
 5580 }
 5581 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
 5582 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
 5583 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
 5584 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
 5585 if (xoffset || yoffset) {
 5586 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset and yoffset must be zero");
 5587 return false;
 5588 }
 5589 if (width != tex->getWidth(target, level)
 5590 || height != tex->getHeight(target, level)) {
 5591 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions must match existing level");
 5592 return false;
 5593 }
 5594 return validateCompressedTexDimensions(functionName, target, level, width, height, format);
 5595 }
 5596 default:
 5597 return false;
 5598 }
 5599}
 5600
 5601bool WebGLRenderingContextBase::validateDrawMode(const char* functionName, GC3Denum mode)
 5602{
 5603 switch (mode) {
 5604 case GraphicsContext3D::POINTS:
 5605 case GraphicsContext3D::LINE_STRIP:
 5606 case GraphicsContext3D::LINE_LOOP:
 5607 case GraphicsContext3D::LINES:
 5608 case GraphicsContext3D::TRIANGLE_STRIP:
 5609 case GraphicsContext3D::TRIANGLE_FAN:
 5610 case GraphicsContext3D::TRIANGLES:
 5611 return true;
 5612 default:
 5613 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode");
 5614 return false;
 5615 }
 5616}
 5617
 5618bool WebGLRenderingContextBase::validateStencilSettings(const char* functionName)
 5619{
 5620 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
 5621 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match");
 5622 return false;
 5623 }
 5624 return true;
 5625}
 5626
 5627bool WebGLRenderingContextBase::validateStencilFunc(const char* functionName, GC3Denum func)
 5628{
 5629 switch (func) {
 5630 case GraphicsContext3D::NEVER:
 5631 case GraphicsContext3D::LESS:
 5632 case GraphicsContext3D::LEQUAL:
 5633 case GraphicsContext3D::GREATER:
 5634 case GraphicsContext3D::GEQUAL:
 5635 case GraphicsContext3D::EQUAL:
 5636 case GraphicsContext3D::NOTEQUAL:
 5637 case GraphicsContext3D::ALWAYS:
 5638 return true;
 5639 default:
 5640 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function");
 5641 return false;
 5642 }
 5643}
 5644
 5645void WebGLRenderingContextBase::printGLErrorToConsole(const String& message)
 5646{
 5647 if (!m_numGLErrorsToConsoleAllowed)
 5648 return;
 5649
 5650 --m_numGLErrorsToConsoleAllowed;
 5651 printWarningToConsole(message);
 5652
 5653 if (!m_numGLErrorsToConsoleAllowed)
 5654 printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context.");
 5655}
 5656
 5657void WebGLRenderingContextBase::printWarningToConsole(const String& message)
 5658{
 5659 if (!canvas())
 5660 return;
 5661 canvas()->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Warning, message);
 5662}
 5663
 5664bool WebGLRenderingContextBase::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
 5665{
 5666 if (target != GraphicsContext3D::FRAMEBUFFER) {
 5667 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
 5668 return false;
 5669 }
 5670 switch (attachment) {
 5671 case GraphicsContext3D::COLOR_ATTACHMENT0:
 5672 case GraphicsContext3D::DEPTH_ATTACHMENT:
 5673 case GraphicsContext3D::STENCIL_ATTACHMENT:
 5674 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
 5675 break;
 5676 default:
 5677 if (m_webglDrawBuffers
 5678 && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
 5679 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
 5680 break;
 5681 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
 5682 return false;
 5683 }
 5684 return true;
 5685}
 5686
 5687bool WebGLRenderingContextBase::validateBlendEquation(const char* functionName, GC3Denum mode)
 5688{
 5689 switch (mode) {
 5690 case GraphicsContext3D::FUNC_ADD:
 5691 case GraphicsContext3D::FUNC_SUBTRACT:
 5692 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
 5693 case Extensions3D::MIN_EXT:
 5694 case Extensions3D::MAX_EXT:
 5695 if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) {
 5696 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
 5697 return false;
 5698 }
 5699 return true;
 5700 break;
 5701 default:
 5702 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
 5703 return false;
 5704 }
 5705}
 5706
 5707bool WebGLRenderingContextBase::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst)
 5708{
 5709 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
 5710 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
 5711 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
 5712 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
 5713 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst");
 5714 return false;
 5715 }
 5716 return true;
 5717}
 5718
 5719bool WebGLRenderingContextBase::validateCapability(const char* functionName, GC3Denum cap)
 5720{
 5721 switch (cap) {
 5722 case GraphicsContext3D::BLEND:
 5723 case GraphicsContext3D::CULL_FACE:
 5724 case GraphicsContext3D::DEPTH_TEST:
 5725 case GraphicsContext3D::DITHER:
 5726 case GraphicsContext3D::POLYGON_OFFSET_FILL:
 5727 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
 5728 case GraphicsContext3D::SAMPLE_COVERAGE:
 5729 case GraphicsContext3D::SCISSOR_TEST:
 5730 case GraphicsContext3D::STENCIL_TEST:
 5731 return true;
 5732 default:
 5733 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
 5734 return false;
 5735 }
 5736}
 5737
 5738bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
 5739{
 5740 if (!v) {
 5741 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5742 return false;
 5743 }
 5744 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
 5745}
 5746
 5747bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
 5748{
 5749 if (!v) {
 5750 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5751 return false;
 5752 }
 5753 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
 5754}
 5755
 5756bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
 5757{
 5758 return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize);
 5759}
 5760
 5761bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
 5762{
 5763 if (!v) {
 5764 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5765 return false;
 5766 }
 5767 return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize);
 5768}
 5769
 5770bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
 5771{
 5772 if (!location)
 5773 return false;
 5774 if (location->program() != m_currentProgram) {
 5775 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program");
 5776 return false;
 5777 }
 5778 if (!v) {
 5779 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5780 return false;
 5781 }
 5782 if (transpose) {
 5783 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE");
 5784 return false;
 5785 }
 5786 if (size < requiredMinSize || (size % requiredMinSize)) {
 5787 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
 5788 return false;
 5789 }
 5790 return true;
 5791}
 5792
 5793WebGLBuffer* WebGLRenderingContextBase::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage)
 5794{
 5795 WebGLBuffer* buffer = 0;
 5796 switch (target) {
 5797 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
 5798 buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
 5799 break;
 5800 case GraphicsContext3D::ARRAY_BUFFER:
 5801 buffer = m_boundArrayBuffer.get();
 5802 break;
 5803 default:
 5804 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
 5805 return nullptr;
 5806 }
 5807 if (!buffer) {
 5808 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer");
 5809 return nullptr;
 5810 }
 5811 switch (usage) {
 5812 case GraphicsContext3D::STREAM_DRAW:
 5813 case GraphicsContext3D::STATIC_DRAW:
 5814 case GraphicsContext3D::DYNAMIC_DRAW:
 5815 return buffer;
 5816 }
 5817 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage");
 5818 return nullptr;
 5819}
 5820
 5821bool WebGLRenderingContextBase::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionCode& ec)
 5822{
 5823 if (!image || !image->cachedImage()) {
 5824 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image");
 5825 return false;
 5826 }
 5827 const URL& url = image->cachedImage()->response().url();
 5828 if (url.isNull() || url.isEmpty() || !url.isValid()) {
 5829 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image");
 5830 return false;
 5831 }
 5832 if (wouldTaintOrigin(image)) {
 5833 ec = SECURITY_ERR;
 5834 return false;
 5835 }
 5836 return true;
 5837}
 5838
 5839bool WebGLRenderingContextBase::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionCode& ec)
 5840{
 5841 if (!canvas || !canvas->buffer()) {
 5842 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no canvas");
 5843 return false;
 5844 }
 5845 if (wouldTaintOrigin(canvas)) {
 5846 ec = SECURITY_ERR;
 5847 return false;
 5848 }
 5849 return true;
 5850}
 5851
 5852#if ENABLE(VIDEO)
 5853bool WebGLRenderingContextBase::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionCode& ec)
 5854{
 5855 if (!video || !video->videoWidth() || !video->videoHeight()) {
 5856 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no video");
 5857 return false;
 5858 }
 5859 if (wouldTaintOrigin(video)) {
 5860 ec = SECURITY_ERR;
 5861 return false;
 5862 }
 5863 return true;
 5864}
 5865#endif
 5866
 5867void WebGLRenderingContextBase::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
 5868{
 5869 if (isContextLostOrPending())
 5870 return;
 5871 if (index >= m_maxVertexAttribs) {
 5872 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
 5873 return;
 5874 }
 5875 // In GL, we skip setting vertexAttrib0 values.
 5876 if (index || isGLES2Compliant()) {
 5877 switch (expectedSize) {
 5878 case 1:
 5879 m_context->vertexAttrib1f(index, v0);
 5880 break;
 5881 case 2:
 5882 m_context->vertexAttrib2f(index, v0, v1);
 5883 break;
 5884 case 3:
 5885 m_context->vertexAttrib3f(index, v0, v1, v2);
 5886 break;
 5887 case 4:
 5888 m_context->vertexAttrib4f(index, v0, v1, v2, v3);
 5889 break;
 5890 }
 5891 }
 5892 VertexAttribValue& attribValue = m_vertexAttribValue[index];
 5893 attribValue.value[0] = v0;
 5894 attribValue.value[1] = v1;
 5895 attribValue.value[2] = v2;
 5896 attribValue.value[3] = v3;
 5897}
 5898
 5899void WebGLRenderingContextBase::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
 5900{
 5901 if (isContextLostOrPending())
 5902 return;
 5903 if (!v) {
 5904 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5905 return;
 5906 }
 5907 vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize);
 5908}
 5909
 5910void WebGLRenderingContextBase::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
 5911{
 5912 if (isContextLostOrPending())
 5913 return;
 5914 if (!v) {
 5915 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
 5916 return;
 5917 }
 5918 if (size < expectedSize) {
 5919 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
 5920 return;
 5921 }
 5922 if (index >= m_maxVertexAttribs) {
 5923 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
 5924 return;
 5925 }
 5926 // In GL, we skip setting vertexAttrib0 values.
 5927 if (index || isGLES2Compliant()) {
 5928 switch (expectedSize) {
 5929 case 1:
 5930 m_context->vertexAttrib1fv(index, v);
 5931 break;
 5932 case 2:
 5933 m_context->vertexAttrib2fv(index, v);
 5934 break;
 5935 case 3:
 5936 m_context->vertexAttrib3fv(index, v);
 5937 break;
 5938 case 4:
 5939 m_context->vertexAttrib4fv(index, v);
 5940 break;
 5941 }
 5942 }
 5943 VertexAttribValue& attribValue = m_vertexAttribValue[index];
 5944 attribValue.initValue();
 5945 for (int ii = 0; ii < expectedSize; ++ii)
 5946 attribValue.value[ii] = v[ii];
 5947}
 5948
 5949void WebGLRenderingContextBase::initVertexAttrib0()
 5950{
 5951 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
 5952
 5953 m_vertexAttrib0Buffer = createBuffer();
 5954 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
 5955 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
 5956 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
 5957 state.bufferBinding = m_vertexAttrib0Buffer;
 5958 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
 5959 m_context->enableVertexAttribArray(0);
 5960 m_vertexAttrib0BufferSize = 0;
 5961 m_vertexAttrib0BufferValue[0] = 0.0f;
 5962 m_vertexAttrib0BufferValue[1] = 0.0f;
 5963 m_vertexAttrib0BufferValue[2] = 0.0f;
 5964 m_vertexAttrib0BufferValue[3] = 1.0f;
 5965 m_forceAttrib0BufferRefill = false;
 5966 m_vertexAttrib0UsedBefore = false;
 5967}
 5968
 5969bool WebGLRenderingContextBase::simulateVertexAttrib0(GC3Dsizei numVertex)
 5970{
 5971 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
 5972 const VertexAttribValue& attribValue = m_vertexAttribValue[0];
 5973 if (!m_currentProgram)
 5974 return false;
 5975 bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
 5976 if (usingVertexAttrib0)
 5977 m_vertexAttrib0UsedBefore = true;
 5978 if (state.enabled && usingVertexAttrib0)
 5979 return false;
 5980 if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
 5981 return false;
 5982 m_vertexAttrib0UsedBefore = true;
 5983 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
 5984 GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
 5985 if (bufferDataSize > m_vertexAttrib0BufferSize) {
 5986 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
 5987 m_vertexAttrib0BufferSize = bufferDataSize;
 5988 m_forceAttrib0BufferRefill = true;
 5989 }
 5990 if (usingVertexAttrib0
 5991 && (m_forceAttrib0BufferRefill
 5992 || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
 5993 || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
 5994 || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
 5995 || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
 5996 auto bufferData = std::make_unique<GC3Dfloat[]>((numVertex + 1) * 4);
 5997 for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
 5998 bufferData[ii * 4] = attribValue.value[0];
 5999 bufferData[ii * 4 + 1] = attribValue.value[1];
 6000 bufferData[ii * 4 + 2] = attribValue.value[2];
 6001 bufferData[ii * 4 + 3] = attribValue.value[3];
 6002 }
 6003 m_vertexAttrib0BufferValue[0] = attribValue.value[0];
 6004 m_vertexAttrib0BufferValue[1] = attribValue.value[1];
 6005 m_vertexAttrib0BufferValue[2] = attribValue.value[2];
 6006 m_vertexAttrib0BufferValue[3] = attribValue.value[3];
 6007 m_forceAttrib0BufferRefill = false;
 6008 m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
 6009 }
 6010 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
 6011 return true;
 6012}
 6013
 6014void WebGLRenderingContextBase::restoreStatesAfterVertexAttrib0Simulation()
 6015{
 6016 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
 6017 if (state.bufferBinding != m_vertexAttrib0Buffer) {
 6018 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
 6019 m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
 6020 }
 6021 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
 6022}
 6023
 6024void WebGLRenderingContextBase::dispatchContextLostEvent()
 6025{
 6026 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
 6027 canvas()->dispatchEvent(event);
 6028 m_restoreAllowed = event->defaultPrevented();
 6029 if (m_contextLostMode == RealLostContext && m_restoreAllowed)
 6030 m_restoreTimer.startOneShot(0);
 6031}
 6032
 6033void WebGLRenderingContextBase::maybeRestoreContext()
 6034{
 6035 ASSERT(m_contextLost);
 6036 if (!m_contextLost)
 6037 return;
 6038
 6039 // The rendering context is not restored unless the default behavior of the
 6040 // webglcontextlost event was prevented earlier.
 6041 //
 6042 // Because of the way m_restoreTimer is set up for real vs. synthetic lost
 6043 // context events, we don't have to worry about this test short-circuiting
 6044 // the retry loop for real context lost events.
 6045 if (!m_restoreAllowed)
 6046 return;
 6047
 6048 int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
 6049
 6050 switch (contextLostReason) {
 6051 case GraphicsContext3D::NO_ERROR:
 6052 // The GraphicsContext3D implementation might not fully
 6053 // support GL_ARB_robustness semantics yet. Alternatively, the
 6054 // WEBGL_lose_context extension might have been used to force
 6055 // a lost context.
 6056 break;
 6057 case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
 6058 // The rendering context is not restored if this context was
 6059 // guilty of causing the graphics reset.
 6060 printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
 6061 return;
 6062 case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
 6063 // Always allow the context to be restored.
 6064 break;
 6065 case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
 6066 // Warn. Ideally, prompt the user telling them that WebGL
 6067 // content on the page might have caused the graphics card to
 6068 // reset and ask them whether they want to continue running
 6069 // the content. Only if they say "yes" should we start
 6070 // attempting to restore the context.
 6071 printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
 6072 break;
 6073 }
 6074
 6075 Frame* frame = canvas()->document().frame();
 6076 if (!frame)
 6077 return;
 6078
 6079 if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled()))
 6080 return;
 6081
 6082 FrameView* view = frame->view();
 6083 if (!view)
 6084 return;
 6085 ScrollView* root = view->root();
 6086 if (!root)
 6087 return;
 6088 HostWindow* hostWindow = root->hostWindow();
 6089 if (!hostWindow)
 6090 return;
 6091
 6092 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, hostWindow));
 6093 if (!context) {
 6094 if (m_contextLostMode == RealLostContext)
 6095 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
 6096 else
 6097 // This likely shouldn't happen but is the best way to report it to the WebGL app.
 6098 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context");
 6099 return;
 6100 }
 6101
 6102 // Construct a new drawing buffer with the new GraphicsContext3D.
 6103 if (m_drawingBuffer) {
 6104 m_drawingBuffer->discardResources();
 6105 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
 6106 DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
 6107 m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha);
 6108 m_drawingBuffer->bind();
 6109 }
 6110
 6111 m_context = context;
 6112 m_contextLost = false;
 6113 setupFlags();
 6114 initializeNewContext();
 6115 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
 6116}
 6117
 6118String WebGLRenderingContextBase::ensureNotNull(const String& text) const
 6119{
 6120 if (text.isNull())
 6121 return WTF::emptyString();
 6122 return text;
 6123}
 6124
 6125WebGLRenderingContextBase::LRUImageBufferCache::LRUImageBufferCache(int capacity)
 6126 : m_buffers(std::make_unique<std::unique_ptr<ImageBuffer>[]>(capacity))
 6127 , m_capacity(capacity)
 6128{
 6129}
 6130
 6131ImageBuffer* WebGLRenderingContextBase::LRUImageBufferCache::imageBuffer(const IntSize& size)
 6132{
 6133 int i;
 6134 for (i = 0; i < m_capacity; ++i) {
 6135 ImageBuffer* buf = m_buffers[i].get();
 6136 if (!buf)
 6137 break;
 6138 if (buf->logicalSize() != size)
 6139 continue;
 6140 bubbleToFront(i);
 6141 return buf;
 6142 }
 6143
 6144 std::unique_ptr<ImageBuffer> temp = ImageBuffer::create(size, 1);
 6145 if (!temp)
 6146 return nullptr;
 6147 i = std::min(m_capacity - 1, i);
 6148 m_buffers[i] = WTF::move(temp);
 6149
 6150 ImageBuffer* buf = m_buffers[i].get();
 6151 bubbleToFront(i);
 6152 return buf;
 6153}
 6154
 6155void WebGLRenderingContextBase::LRUImageBufferCache::bubbleToFront(int idx)
 6156{
 6157 for (int i = idx; i > 0; --i)
 6158 m_buffers[i].swap(m_buffers[i-1]);
 6159}
 6160
 6161namespace {
 6162
 6163 String GetErrorString(GC3Denum error)
 6164 {
 6165 switch (error) {
 6166 case GraphicsContext3D::INVALID_ENUM:
 6167 return "INVALID_ENUM";
 6168 case GraphicsContext3D::INVALID_VALUE:
 6169 return "INVALID_VALUE";
 6170 case GraphicsContext3D::INVALID_OPERATION:
 6171 return "INVALID_OPERATION";
 6172 case GraphicsContext3D::OUT_OF_MEMORY:
 6173 return "OUT_OF_MEMORY";
 6174 case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
 6175 return "INVALID_FRAMEBUFFER_OPERATION";
 6176 case GraphicsContext3D::CONTEXT_LOST_WEBGL:
 6177 return "CONTEXT_LOST_WEBGL";
 6178 default:
 6179 return String::format("WebGL ERROR(%04x)", error);
 6180 }
 6181 }
 6182
 6183} // namespace anonymous
 6184
 6185void WebGLRenderingContextBase::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display)
 6186{
 6187 if (m_synthesizedErrorsToConsole && display == DisplayInConsole) {
 6188 String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description);
 6189 printGLErrorToConsole(str);
 6190 }
 6191 m_context->synthesizeGLError(error);
 6192}
 6193
 6194
 6195void WebGLRenderingContextBase::printGLWarningToConsole(const char* functionName, const char* description)
 6196{
 6197 if (m_synthesizedErrorsToConsole) {
 6198 String str = String("WebGL: ") + String(functionName) + ": " + String(description);
 6199 printGLErrorToConsole(str);
 6200 }
 6201}
 6202
 6203void WebGLRenderingContextBase::applyStencilTest()
 6204{
 6205 bool haveStencilBuffer = false;
 6206
 6207 if (m_framebufferBinding)
 6208 haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
 6209 else {
 6210 RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
 6211 haveStencilBuffer = attributes->stencil();
 6212 }
 6213 enableOrDisable(GraphicsContext3D::STENCIL_TEST,
 6214 m_stencilEnabled && haveStencilBuffer);
 6215}
 6216
 6217void WebGLRenderingContextBase::enableOrDisable(GC3Denum capability, bool enable)
 6218{
 6219 if (enable)
 6220 m_context->enable(capability);
 6221 else
 6222 m_context->disable(capability);
 6223}
 6224
 6225IntSize WebGLRenderingContextBase::clampedCanvasSize()
 6226{
 6227 return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
 6228 clamp(canvas()->height(), 1, m_maxViewportDims[1]));
 6229}
 6230
 6231GC3Dint WebGLRenderingContextBase::getMaxDrawBuffers()
 6232{
 6233 if (!supportsDrawBuffers())
 6234 return 0;
 6235 if (!m_maxDrawBuffers)
 6236 m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
 6237 if (!m_maxColorAttachments)
 6238 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
 6239 // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
 6240 return std::min(m_maxDrawBuffers, m_maxColorAttachments);
 6241}
 6242
 6243GC3Dint WebGLRenderingContextBase::getMaxColorAttachments()
 6244{
 6245 if (!supportsDrawBuffers())
 6246 return 0;
 6247 if (!m_maxColorAttachments)
 6248 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
 6249 return m_maxColorAttachments;
 6250}
 6251
 6252void WebGLRenderingContextBase::setBackDrawBuffer(GC3Denum buf)
 6253{
 6254 m_backDrawBuffer = buf;
 6255}
 6256
 6257void WebGLRenderingContextBase::restoreCurrentFramebuffer()
 6258{
 6259 ExceptionCode ec;
 6260 bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get(), ec);
 6261}
 6262
 6263void WebGLRenderingContextBase::restoreCurrentTexture2D()
 6264{
 6265 ExceptionCode ec;
 6266 bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUnit].texture2DBinding.get(), ec);
 6267}
 6268
 6269bool WebGLRenderingContextBase::supportsDrawBuffers()
 6270{
 6271 if (!m_drawBuffersWebGLRequirementsChecked) {
 6272 m_drawBuffersWebGLRequirementsChecked = true;
 6273 m_drawBuffersSupported = WebGLDrawBuffers::supported(this);
 6274 }
 6275 return m_drawBuffersSupported;
 6276}
 6277
 6278void WebGLRenderingContextBase::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
 6279{
 6280 if (!primcount) {
 6281 markContextChanged();
 6282 return;
 6283 }
 6284
 6285 if (!validateDrawArrays("drawArraysInstanced", mode, first, count, primcount))
 6286 return;
 6287
 6288 clearIfComposited();
 6289
 6290 bool vertexAttrib0Simulated = false;
 6291 if (!isGLES2Compliant())
 6292 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
 6293 if (!isGLES2NPOTStrict())
 6294 checkTextureCompleteness("drawArraysInstanced", true);
 6295
 6296 m_context->drawArraysInstanced(mode, first, count, primcount);
 6297
 6298 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 6299 restoreStatesAfterVertexAttrib0Simulation();
 6300 if (!isGLES2NPOTStrict())
 6301 checkTextureCompleteness("drawArraysInstanced", false);
 6302 markContextChanged();
 6303}
 6304
 6305void WebGLRenderingContextBase::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount)
 6306{
 6307 if (!primcount) {
 6308 markContextChanged();
 6309 return;
 6310 }
 6311
 6312 unsigned numElements = 0;
 6313 if (!validateDrawElements("drawElementsInstanced", mode, count, type, offset, numElements, primcount))
 6314 return;
 6315
 6316 clearIfComposited();
 6317
 6318 bool vertexAttrib0Simulated = false;
 6319 if (!isGLES2Compliant()) {
 6320 if (!numElements)
 6321 validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
 6322 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
 6323 }
 6324 if (!isGLES2NPOTStrict())
 6325 checkTextureCompleteness("drawElementsInstanced", true);
 6326
 6327 m_context->drawElementsInstanced(mode, count, type, static_cast<GC3Dintptr>(offset), primcount);
 6328
 6329 if (!isGLES2Compliant() && vertexAttrib0Simulated)
 6330 restoreStatesAfterVertexAttrib0Simulation();
 6331 if (!isGLES2NPOTStrict())
 6332 checkTextureCompleteness("drawElementsInstanced", false);
 6333 markContextChanged();
 6334}
 6335
 6336void WebGLRenderingContextBase::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
 6337{
 6338 if (isContextLostOrPending())
 6339 return;
 6340
 6341 if (index >= m_maxVertexAttribs) {
 6342 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor", "index out of range");
 6343 return;
 6344 }
 6345
 6346 m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor);
 6347 m_context->vertexAttribDivisor(index, divisor);
 6348}
 6349
 6350
 6351} // namespace WebCore
 6352
 6353#endif // ENABLE(WEBGL)
0

Source/WebCore/html/canvas/WebGLRenderingContextBase.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WebGLRenderingContextBase_h
 27#define WebGLRenderingContextBase_h
 28
 29#include "ActiveDOMObject.h"
 30#include "CanvasRenderingContext.h"
 31#include "DrawingBuffer.h"
 32#include "GraphicsContext3D.h"
 33#include "ImageBuffer.h"
 34#include "Timer.h"
 35#include "WebGLGetInfo.h"
 36#include <memory>
 37#include <runtime/Float32Array.h>
 38#include <runtime/Int32Array.h>
 39#include <wtf/text/WTFString.h>
 40
 41namespace WebCore {
 42
 43class ANGLEInstancedArrays;
 44class EXTBlendMinMax;
 45class EXTTextureFilterAnisotropic;
 46class EXTShaderTextureLOD;
 47class EXTsRGB;
 48class EXTFragDepth;
 49class HTMLImageElement;
 50class HTMLVideoElement;
 51class ImageBuffer;
 52class ImageData;
 53class IntSize;
 54class OESStandardDerivatives;
 55class OESTextureFloat;
 56class OESTextureFloatLinear;
 57class OESTextureHalfFloat;
 58class OESTextureHalfFloatLinear;
 59class OESVertexArrayObject;
 60class OESElementIndexUint;
 61class WebGLActiveInfo;
 62class WebGLBuffer;
 63class WebGLContextGroup;
 64class WebGLContextObject;
 65class WebGLCompressedTextureATC;
 66class WebGLCompressedTexturePVRTC;
 67class WebGLCompressedTextureS3TC;
 68class WebGLContextAttributes;
 69class WebGLDebugRendererInfo;
 70class WebGLDebugShaders;
 71class WebGLDepthTexture;
 72class WebGLDrawBuffers;
 73class WebGLExtension;
 74class WebGLFramebuffer;
 75class WebGLLoseContext;
 76class WebGLObject;
 77class WebGLProgram;
 78class WebGLRenderbuffer;
 79class WebGLShader;
 80class WebGLSharedObject;
 81class WebGLShaderPrecisionFormat;
 82class WebGLTexture;
 83class WebGLUniformLocation;
 84class WebGLVertexArrayObjectOES;
 85
 86typedef int ExceptionCode;
 87
 88class WebGLRenderingContextBase : public CanvasRenderingContext, public ActiveDOMObject {
 89public:
 90 static std::unique_ptr<WebGLRenderingContextBase> create(HTMLCanvasElement*, WebGLContextAttributes*, const String&);
 91 virtual ~WebGLRenderingContextBase();
 92
 93 virtual bool is3d() const override { return true; }
 94#if PLATFORM(WIN)
 95// FIXME: Implement accelerated 3d canvas on Windows.
 96virtual bool isAccelerated() const override { return false; }
 97#else
 98virtual bool isAccelerated() const override { return true; }
 99#endif
 100
 101int drawingBufferWidth() const;
 102int drawingBufferHeight() const;
 103
 104void activeTexture(GC3Denum texture, ExceptionCode&);
 105void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
 106void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&);
 107void bindBuffer(GC3Denum target, WebGLBuffer*, ExceptionCode&);
 108void bindFramebuffer(GC3Denum target, WebGLFramebuffer*, ExceptionCode&);
 109void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*, ExceptionCode&);
 110void bindTexture(GC3Denum target, WebGLTexture*, ExceptionCode&);
 111void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
 112void blendEquation(GC3Denum mode);
 113void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
 114void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
 115void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
 116
 117void bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode&);
 118void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode&);
 119void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode&);
 120void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode&);
 121void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode&);
 122
 123GC3Denum checkFramebufferStatus(GC3Denum target);
 124void clear(GC3Dbitfield mask);
 125void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
 126void clearDepth(GC3Dfloat);
 127void clearStencil(GC3Dint);
 128void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
 129void compileShader(WebGLShader*, ExceptionCode&);
 130
 131void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
 132 GC3Dsizei height, GC3Dint border, ArrayBufferView* data);
 133void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 134 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
 135
 136void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
 137void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 138
 139PassRefPtr<WebGLBuffer> createBuffer();
 140PassRefPtr<WebGLFramebuffer> createFramebuffer();
 141PassRefPtr<WebGLProgram> createProgram();
 142PassRefPtr<WebGLRenderbuffer> createRenderbuffer();
 143PassRefPtr<WebGLShader> createShader(GC3Denum type, ExceptionCode&);
 144PassRefPtr<WebGLTexture> createTexture();
 145
 146void cullFace(GC3Denum mode);
 147
 148void deleteBuffer(WebGLBuffer*);
 149void deleteFramebuffer(WebGLFramebuffer*);
 150void deleteProgram(WebGLProgram*);
 151void deleteRenderbuffer(WebGLRenderbuffer*);
 152void deleteShader(WebGLShader*);
 153void deleteTexture(WebGLTexture*);
 154
 155void depthFunc(GC3Denum);
 156void depthMask(GC3Dboolean);
 157void depthRange(GC3Dfloat zNear, GC3Dfloat zFar);
 158void detachShader(WebGLProgram*, WebGLShader*, ExceptionCode&);
 159void disable(GC3Denum cap);
 160void disableVertexAttribArray(GC3Duint index, ExceptionCode&);
 161void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode&);
 162void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode&);
 163
 164void enable(GC3Denum cap);
 165void enableVertexAttribArray(GC3Duint index, ExceptionCode&);
 166void finish();
 167void flush();
 168void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*, ExceptionCode&);
 169void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level, ExceptionCode&);
 170void frontFace(GC3Denum mode);
 171void generateMipmap(GC3Denum target);
 172
 173PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index, ExceptionCode&);
 174PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index, ExceptionCode&);
 175bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader>>&, ExceptionCode&);
 176GC3Dint getAttribLocation(WebGLProgram*, const String& name);
 177WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
 178PassRefPtr<WebGLContextAttributes> getContextAttributes();
 179GC3Denum getError();
 180WebGLExtension* getExtension(const String& name);
 181WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&);
 182WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&);
 183WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname, ExceptionCode&);
 184String getProgramInfoLog(WebGLProgram*, ExceptionCode&);
 185WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
 186WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname, ExceptionCode&);
 187String getShaderInfoLog(WebGLShader*, ExceptionCode&);
 188PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode&);
 189String getShaderSource(WebGLShader*, ExceptionCode&);
 190Vector<String> getSupportedExtensions();
 191WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode&);
 192WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*, ExceptionCode&);
 193PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&, ExceptionCode&);
 194WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode&);
 195long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
 196
 197void hint(GC3Denum target, GC3Denum mode);
 198GC3Dboolean isBuffer(WebGLBuffer*);
 199bool isContextLost() const;
 200GC3Dboolean isEnabled(GC3Denum cap);
 201GC3Dboolean isFramebuffer(WebGLFramebuffer*);
 202GC3Dboolean isProgram(WebGLProgram*);
 203GC3Dboolean isRenderbuffer(WebGLRenderbuffer*);
 204GC3Dboolean isShader(WebGLShader*);
 205GC3Dboolean isTexture(WebGLTexture*);
 206
 207void lineWidth(GC3Dfloat);
 208void linkProgram(WebGLProgram*, ExceptionCode&);
 209void pixelStorei(GC3Denum pname, GC3Dint param);
 210void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
 211void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&);
 212void releaseShaderCompiler();
 213void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
 214void sampleCoverage(GC3Dfloat value, GC3Dboolean invert);
 215void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 216void shaderSource(WebGLShader*, const String&, ExceptionCode&);
 217void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
 218void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
 219void stencilMask(GC3Duint);
 220void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
 221void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
 222void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
 223
 224void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 225 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 226 GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
 227void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 228 GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
 229void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 230 GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
 231void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 232 GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
 233#if ENABLE(VIDEO)
 234void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
 235 GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
 236#endif
 237
 238void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
 239void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
 240
 241void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 242 GC3Dsizei width, GC3Dsizei height,
 243 GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
 244void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 245 GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
 246void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 247 GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
 248void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 249 GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
 250#if ENABLE(VIDEO)
 251void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 252 GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
 253#endif
 254
 255void uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode&);
 256void uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 257void uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 258void uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode&);
 259void uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 260void uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 261void uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode&);
 262void uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 263void uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 264void uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode&);
 265void uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 266void uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 267void uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode&);
 268void uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 269void uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 270void uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode&);
 271void uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 272void uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 273void uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode&);
 274void uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
 275void uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&);
 276void uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode&);
 277void uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
 278void uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&);
 279void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
 280void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
 281void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
 282void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
 283void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&);
 284void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&);
 285
 286void useProgram(WebGLProgram*, ExceptionCode&);
 287void validateProgram(WebGLProgram*, ExceptionCode&);
 288
 289void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
 290void vertexAttrib1fv(GC3Duint index, Float32Array* values);
 291void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 292void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
 293void vertexAttrib2fv(GC3Duint index, Float32Array* values);
 294void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 295void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
 296void vertexAttrib3fv(GC3Duint index, Float32Array* values);
 297void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 298void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
 299void vertexAttrib4fv(GC3Duint index, Float32Array* values);
 300void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size);
 301void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
 302 GC3Dsizei stride, long long offset, ExceptionCode&);
 303
 304void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 305
 306// WEBKIT_lose_context support
 307enum LostContextMode {
 308 // Lost context occurred at the graphics system level.
 309 RealLostContext,
 310
 311 // Lost context provoked by WEBKIT_lose_context.
 312 SyntheticLostContext
 313};
 314void forceLostContext(LostContextMode);
 315void forceRestoreContext();
 316void loseContextImpl(LostContextMode);
 317
 318GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
 319WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
 320virtual PlatformLayer* platformLayer() const override;
 321
 322void reshape(int width, int height);
 323
 324void markLayerComposited();
 325virtual void paintRenderingResultsToCanvas() override;
 326PassRefPtr<ImageData> paintRenderingResultsToImageData();
 327
 328void removeSharedObject(WebGLSharedObject*);
 329void removeContextObject(WebGLContextObject*);
 330
 331unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; }
 332
 333// ANGLE_instanced_arrays extension functions.
 334void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
 335void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount);
 336void vertexAttribDivisor(GC3Duint index, GC3Duint divisor);
 337
 338protected:
 339WebGLRenderingContextBase(HTMLCanvasElement*, GraphicsContext3D::Attributes);
 340WebGLRenderingContextBase(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes);
 341
 342private:
 343friend class WebGLDrawBuffers;
 344friend class WebGLFramebuffer;
 345friend class WebGLObject;
 346friend class OESVertexArrayObject;
 347friend class WebGLDebugShaders;
 348friend class WebGLCompressedTextureATC;
 349friend class WebGLCompressedTexturePVRTC;
 350friend class WebGLCompressedTextureS3TC;
 351friend class WebGLRenderingContextErrorMessageCallback;
 352friend class WebGLVertexArrayObjectOES;
 353
 354void initializeNewContext();
 355void setupFlags();
 356
 357// ActiveDOMObject
 358virtual bool hasPendingActivity() const override;
 359virtual void stop() override;
 360virtual const char* activeDOMObjectName() const override { return "WebGLRenderingContext"; }
 361
 362void addSharedObject(WebGLSharedObject*);
 363void addContextObject(WebGLContextObject*);
 364void detachAndRemoveAllObjects();
 365
 366void destroyGraphicsContext3D();
 367void markContextChanged();
 368
 369// Query whether it is built on top of compliant GLES2 implementation.
 370bool isGLES2Compliant() { return m_isGLES2Compliant; }
 371// Query if the GL implementation is NPOT strict.
 372bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; }
 373// Query if the GL implementation generates errors on out-of-bounds buffer accesses.
 374bool isErrorGeneratedOnOutOfBoundsAccesses() { return m_isErrorGeneratedOnOutOfBoundsAccesses; }
 375// Query if the GL implementation initializes textures/renderbuffers to 0.
 376bool isResourceSafe() { return m_isResourceSafe; }
 377// Query if depth_stencil buffer is supported.
 378bool isDepthStencilSupported() { return m_isDepthStencilSupported; }
 379
 380// Helper to return the size in bytes of OpenGL data types
 381// like GL_FLOAT, GL_INT, etc.
 382unsigned sizeInBytes(GC3Denum type);
 383
 384// Basic validation of count and offset against number of elements in element array buffer
 385bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
 386
 387// Conservative but quick index validation
 388bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired);
 389
 390// Precise but slow index validation -- only done if conservative checks fail
 391bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired);
 392bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0);
 393
 394bool validateWebGLObject(const char*, WebGLObject*);
 395
 396bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
 397bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount);
 398
 399// Adds a compressed texture format.
 400void addCompressedTextureFormat(GC3Denum);
 401
 402PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, int deviceScaleFactor);
 403
 404#if ENABLE(VIDEO)
 405PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy, ExceptionCode&);
 406#endif
 407
 408RefPtr<GraphicsContext3D> m_context;
 409RefPtr<WebGLContextGroup> m_contextGroup;
 410
 411// Optional structure for rendering to a DrawingBuffer, instead of directly
 412// to the back-buffer of m_context.
 413RefPtr<DrawingBuffer> m_drawingBuffer;
 414
 415// Dispatches a context lost event once it is determined that one is needed.
 416// This is used both for synthetic and real context losses. For real ones, it's
 417// likely that there's no JavaScript on the stack, but that might be dependent
 418// on how exactly the platform discovers that the context was lost. For better
 419// portability we always defer the dispatch of the event.
 420Timer m_dispatchContextLostEventTimer;
 421bool m_restoreAllowed;
 422Timer m_restoreTimer;
 423
 424bool m_needsUpdate;
 425bool m_markedCanvasDirty;
 426HashSet<WebGLContextObject*> m_contextObjects;
 427
 428// List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
 429RefPtr<WebGLBuffer> m_boundArrayBuffer;
 430
 431RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject;
 432RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject;
 433void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject)
 434{
 435 if (arrayObject)
 436 m_boundVertexArrayObject = arrayObject;
 437 else
 438 m_boundVertexArrayObject = m_defaultVertexArrayObject;
 439}
 440
 441class VertexAttribValue {
 442public:
 443 VertexAttribValue()
 444 {
 445 initValue();
 446 }
 447
 448 void initValue()
 449 {
 450 value[0] = 0.0f;
 451 value[1] = 0.0f;
 452 value[2] = 0.0f;
 453 value[3] = 1.0f;
 454 }
 455
 456 GC3Dfloat value[4];
 457};
 458Vector<VertexAttribValue> m_vertexAttribValue;
 459unsigned m_maxVertexAttribs;
 460RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
 461long m_vertexAttrib0BufferSize;
 462GC3Dfloat m_vertexAttrib0BufferValue[4];
 463bool m_forceAttrib0BufferRefill;
 464bool m_vertexAttrib0UsedBefore;
 465
 466RefPtr<WebGLProgram> m_currentProgram;
 467RefPtr<WebGLFramebuffer> m_framebufferBinding;
 468RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
 469struct TextureUnitState {
 470 RefPtr<WebGLTexture> texture2DBinding;
 471 RefPtr<WebGLTexture> textureCubeMapBinding;
 472};
 473Vector<TextureUnitState> m_textureUnits;
 474unsigned long m_activeTextureUnit;
 475
 476RefPtr<WebGLTexture> m_blackTexture2D;
 477RefPtr<WebGLTexture> m_blackTextureCubeMap;
 478
 479Vector<GC3Denum> m_compressedTextureFormats;
 480
 481// Fixed-size cache of reusable image buffers for video texImage2D calls.
 482class LRUImageBufferCache {
 483public:
 484 LRUImageBufferCache(int capacity);
 485 // The pointer returned is owned by the image buffer map.
 486 ImageBuffer* imageBuffer(const IntSize& size);
 487private:
 488 void bubbleToFront(int idx);
 489 std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers;
 490 int m_capacity;
 491};
 492LRUImageBufferCache m_generatedImageCache;
 493
 494GC3Dint m_maxTextureSize;
 495GC3Dint m_maxCubeMapTextureSize;
 496GC3Dint m_maxRenderbufferSize;
 497GC3Dint m_maxViewportDims[2];
 498GC3Dint m_maxTextureLevel;
 499GC3Dint m_maxCubeMapTextureLevel;
 500
 501GC3Dint m_maxDrawBuffers;
 502GC3Dint m_maxColorAttachments;
 503GC3Denum m_backDrawBuffer;
 504bool m_drawBuffersWebGLRequirementsChecked;
 505bool m_drawBuffersSupported;
 506
 507GC3Dint m_packAlignment;
 508GC3Dint m_unpackAlignment;
 509bool m_unpackFlipY;
 510bool m_unpackPremultiplyAlpha;
 511GC3Denum m_unpackColorspaceConversion;
 512bool m_contextLost;
 513LostContextMode m_contextLostMode;
 514GraphicsContext3D::Attributes m_attributes;
 515
 516bool m_layerCleared;
 517GC3Dfloat m_clearColor[4];
 518bool m_scissorEnabled;
 519GC3Dfloat m_clearDepth;
 520GC3Dint m_clearStencil;
 521GC3Dboolean m_colorMask[4];
 522GC3Dboolean m_depthMask;
 523
 524bool m_stencilEnabled;
 525GC3Duint m_stencilMask, m_stencilMaskBack;
 526GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
 527GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack;
 528
 529bool m_isGLES2Compliant;
 530bool m_isGLES2NPOTStrict;
 531bool m_isErrorGeneratedOnOutOfBoundsAccesses;
 532bool m_isResourceSafe;
 533bool m_isDepthStencilSupported;
 534bool m_isRobustnessEXTSupported;
 535
 536bool m_synthesizedErrorsToConsole;
 537int m_numGLErrorsToConsoleAllowed;
 538
 539// A WebGLRenderingContext can be created in a state where it appears as
 540// a valid and active context, but will not execute any important operations
 541// until its load policy is completely resolved.
 542bool m_isPendingPolicyResolution;
 543bool m_hasRequestedPolicyResolution;
 544bool isContextLostOrPending();
 545
 546// Enabled extension objects.
 547std::unique_ptr<EXTFragDepth> m_extFragDepth;
 548std::unique_ptr<EXTBlendMinMax> m_extBlendMinMax;
 549std::unique_ptr<EXTsRGB> m_extsRGB;
 550std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic;
 551std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD;
 552std::unique_ptr<OESTextureFloat> m_oesTextureFloat;
 553std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear;
 554std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat;
 555std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear;
 556std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives;
 557std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject;
 558std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint;
 559std::unique_ptr<WebGLLoseContext> m_webglLoseContext;
 560std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo;
 561std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders;
 562std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC;
 563std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC;
 564std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC;
 565std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture;
 566std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers;
 567std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays;
 568
 569// Helpers for getParameter and others
 570WebGLGetInfo getBooleanParameter(GC3Denum);
 571WebGLGetInfo getBooleanArrayParameter(GC3Denum);
 572WebGLGetInfo getFloatParameter(GC3Denum);
 573WebGLGetInfo getIntParameter(GC3Denum);
 574WebGLGetInfo getUnsignedIntParameter(GC3Denum);
 575WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum);
 576WebGLGetInfo getWebGLIntArrayParameter(GC3Denum);
 577
 578// Clear the backbuffer if it was composited since the last operation.
 579// clearMask is set to the bitfield of any clear that would happen anyway at this time
 580// and the function returns true if that clear is now unnecessary.
 581bool clearIfComposited(GC3Dbitfield clearMask = 0);
 582
 583// Helper to restore state that clearing the framebuffer may destroy.
 584void restoreStateAfterClear();
 585
 586void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
 587void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
 588void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
 589void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
 590
 591void checkTextureCompleteness(const char*, bool);
 592
 593void createFallbackBlackTextures1x1();
 594
 595// Helper function for copyTex{Sub}Image, check whether the internalformat
 596// and the color buffer format of the current bound framebuffer combination
 597// is valid.
 598bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,GC3Denum colorBufferFormat);
 599
 600// Helper function to get the bound framebuffer's color buffer format.
 601GC3Denum getBoundFramebufferColorFormat();
 602
 603// Helper function to get the bound framebuffer's width.
 604int getBoundFramebufferWidth();
 605
 606// Helper function to get the bound framebuffer's height.
 607int getBoundFramebufferHeight();
 608
 609// Helper function to verify limits on the length of uniform and attribute locations.
 610bool validateLocationLength(const char* functionName, const String&);
 611
 612// Helper function to check if size is non-negative.
 613// Generate GL error and return false for negative inputs; otherwise, return true.
 614bool validateSize(const char* functionName, GC3Dint x, GC3Dint y);
 615
 616// Helper function to check if all characters in the string belong to the
 617// ASCII subset as defined in GLSL ES 1.0 spec section 3.1.
 618bool validateString(const char* functionName, const String&);
 619
 620// Helper function to check target and texture bound to the target.
 621// Generate GL errors and return 0 if target is invalid or texture bound is
 622// null. Otherwise, return the texture bound to the target.
 623WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap);
 624
 625// Helper function to check input format/type for functions {copy}Tex{Sub}Image.
 626// Generates GL error and returns false if parameters are invalid.
 627bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
 628
 629// Helper function to check input level for functions {copy}Tex{Sub}Image.
 630// Generates GL error and returns false if level is invalid.
 631bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
 632
 633enum TexFuncValidationFunctionType {
 634 NotTexSubImage2D,
 635 TexSubImage2D,
 636};
 637
 638enum TexFuncValidationSourceType {
 639 SourceArrayBufferView,
 640 SourceImageData,
 641 SourceHTMLImageElement,
 642 SourceHTMLCanvasElement,
 643 SourceHTMLVideoElement,
 644};
 645
 646// Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid.
 647// Otherwise, it would return quickly without doing other work.
 648bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
 649 GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset);
 650
 651// Helper function to check input parameters for functions {copy}Tex{Sub}Image.
 652// Generates GL error and returns false if parameters are invalid.
 653bool validateTexFuncParameters(const char* functionName,
 654 TexFuncValidationFunctionType,
 655 GC3Denum target, GC3Dint level,
 656 GC3Denum internalformat,
 657 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
 658 GC3Denum format, GC3Denum type);
 659
 660enum NullDisposition {
 661 NullAllowed,
 662 NullNotAllowed
 663};
 664
 665// Helper function to validate that the given ArrayBufferView
 666// is of the correct type and contains enough data for the texImage call.
 667// Generates GL error and returns false if parameters are invalid.
 668bool validateTexFuncData(const char* functionName, GC3Dint level,
 669 GC3Dsizei width, GC3Dsizei height,
 670 GC3Denum format, GC3Denum type,
 671 ArrayBufferView* pixels,
 672 NullDisposition);
 673
 674// Helper function to validate a given texture format is settable as in
 675// you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
 676// copyTexSubImage2D.
 677// Generates GL error and returns false if the format is not settable.
 678bool validateSettableTexFormat(const char* functionName, GC3Denum format);
 679
 680// Helper function to validate compressed texture data is correct size
 681// for the given format and dimensions.
 682bool validateCompressedTexFuncData(const char* functionName,
 683 GC3Dsizei width, GC3Dsizei height,
 684 GC3Denum format, ArrayBufferView* pixels);
 685
 686// Helper function for validating compressed texture formats.
 687bool validateCompressedTexFormat(GC3Denum format);
 688
 689// Helper function to validate compressed texture dimensions are valid for
 690// the given format.
 691bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
 692
 693// Helper function to validate compressed texture dimensions are valid for
 694// the given format.
 695bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
 696 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
 697
 698// Helper function to validate mode for draw{Arrays/Elements}.
 699bool validateDrawMode(const char* functionName, GC3Denum);
 700
 701// Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
 702bool validateStencilSettings(const char* functionName);
 703
 704// Helper function to validate stencil func.
 705bool validateStencilFunc(const char* functionName, GC3Denum);
 706
 707// Helper function for texParameterf and texParameteri.
 708void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
 709
 710// Helper function to print GL errors to console.
 711void printGLErrorToConsole(const String&);
 712void printGLWarningToConsole(const char* function, const char* reason);
 713
 714// Helper function to print warnings to console. Currently
 715// used only to warn about use of obsolete functions.
 716void printWarningToConsole(const String&);
 717
 718// Helper function to validate input parameters for framebuffer functions.
 719// Generate GL error if parameters are illegal.
 720bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment);
 721
 722// Helper function to validate blend equation mode.
 723bool validateBlendEquation(const char* functionName, GC3Denum);
 724
 725// Helper function to validate blend func factors.
 726bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
 727
 728// Helper function to validate a GL capability.
 729bool validateCapability(const char* functionName, GC3Denum);
 730
 731// Helper function to validate input parameters for uniform functions.
 732bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod);
 733bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod);
 734bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod);
 735bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod);
 736bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod);
 737
 738// Helper function to validate parameters for bufferData.
 739// Return the current bound buffer to target, or 0 if parameters are invalid.
 740WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage);
 741
 742// Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin.
 743bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&);
 744
 745// Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin.
 746bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&);
 747
 748#if ENABLE(VIDEO)
 749// Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin.
 750bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&);
 751#endif
 752
 753// Helper functions for vertexAttribNf{v}.
 754void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat);
 755void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize);
 756void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize);
 757
 758// Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
 759// Return false if caller should return without further processing.
 760bool deleteObject(WebGLObject*);
 761
 762// Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram.
 763// If the object has already been deleted, set deleted to true upon return.
 764// Return false if caller should return without further processing.
 765bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted);
 766
 767// Helpers for simulating vertexAttrib0
 768void initVertexAttrib0();
 769bool simulateVertexAttrib0(GC3Dsizei numVertex);
 770void restoreStatesAfterVertexAttrib0Simulation();
 771
 772void dispatchContextLostEvent();
 773// Helper for restoration after context lost.
 774void maybeRestoreContext();
 775
 776// Determine if we are running privileged code in the browser, for example,
 777// a Safari or Chrome extension.
 778bool allowPrivilegedExtensions() const;
 779
 780enum ConsoleDisplayPreference {
 781 DisplayInConsole,
 782 DontDisplayInConsole
 783};
 784
 785// Wrapper for GraphicsContext3D::synthesizeGLError that sends a message
 786// to the JavaScript console.
 787void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole);
 788
 789String ensureNotNull(const String&) const;
 790
 791// Enable or disable stencil test based on user setting and
 792// whether the current FBO has a stencil buffer.
 793void applyStencilTest();
 794
 795// Helper for enabling or disabling a capability.
 796void enableOrDisable(GC3Denum capability, bool enable);
 797
 798// Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
 799IntSize clampedCanvasSize();
 800
 801// First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0.
 802// Later, return the cached value.
 803GC3Dint getMaxDrawBuffers();
 804GC3Dint getMaxColorAttachments();
 805
 806void setBackDrawBuffer(GC3Denum);
 807
 808void restoreCurrentFramebuffer();
 809void restoreCurrentTexture2D();
 810
 811// Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
 812bool supportsDrawBuffers();
 813};
 814
 815} // namespace WebCore
 816
 817#endif
0

Source/WebCore/html/canvas/WebGLRenderingContextBase.idl

 1/*
 2* Copyright (C) 2015 Apple Inc. All rights reserved.
 3*
 4* Redistribution and use in source and binary forms, with or without
 5* modification, are permitted provided that the following conditions
 6* are met:
 7* 1. Redistributions of source code must retain the above copyright
 8* notice, this list of conditions and the following disclaimer.
 9* 2. Redistributions in binary form must reproduce the above copyright
 10* notice, this list of conditions and the following disclaimer in the
 11* documentation and/or other materials provided with the distribution.
 12*
 13* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24*/
 25
 26typedef unsigned long GLenum;
 27typedef boolean GLboolean;
 28typedef unsigned long GLbitfield;
 29typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */
 30typedef short GLshort;
 31typedef long GLint;
 32typedef long GLsizei;
 33typedef long long GLintptr;
 34typedef long long GLsizeiptr;
 35typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */
 36typedef unsigned short GLushort;
 37typedef unsigned long GLuint;
 38typedef unrestricted float GLfloat;
 39typedef unrestricted float GLclampf;
 40
 41[
 42Conditional=WEBGL,
 43JSCustomMarkFunction,
 44DoNotCheckConstants,
 45] interface WebGLRenderingContextBase : CanvasRenderingContext {
 46
 47/* ClearBufferMask */
 48const GLenum DEPTH_BUFFER_BIT = 0x00000100;
 49const GLenum STENCIL_BUFFER_BIT = 0x00000400;
 50const GLenum COLOR_BUFFER_BIT = 0x00004000;
 51
 52/* BeginMode */
 53const GLenum POINTS = 0x0000;
 54const GLenum LINES = 0x0001;
 55const GLenum LINE_LOOP = 0x0002;
 56const GLenum LINE_STRIP = 0x0003;
 57const GLenum TRIANGLES = 0x0004;
 58const GLenum TRIANGLE_STRIP = 0x0005;
 59const GLenum TRIANGLE_FAN = 0x0006;
 60
 61/* AlphaFunction (not supported in ES20) */
 62/* NEVER */
 63/* LESS */
 64/* EQUAL */
 65/* LEQUAL */
 66/* GREATER */
 67/* NOTEQUAL */
 68/* GEQUAL */
 69/* ALWAYS */
 70
 71/* BlendingFactorDest */
 72const GLenum ZERO = 0;
 73const GLenum ONE = 1;
 74const GLenum SRC_COLOR = 0x0300;
 75const GLenum ONE_MINUS_SRC_COLOR = 0x0301;
 76const GLenum SRC_ALPHA = 0x0302;
 77const GLenum ONE_MINUS_SRC_ALPHA = 0x0303;
 78const GLenum DST_ALPHA = 0x0304;
 79const GLenum ONE_MINUS_DST_ALPHA = 0x0305;
 80
 81/* BlendingFactorSrc */
 82/* ZERO */
 83/* ONE */
 84const GLenum DST_COLOR = 0x0306;
 85const GLenum ONE_MINUS_DST_COLOR = 0x0307;
 86const GLenum SRC_ALPHA_SATURATE = 0x0308;
 87/* SRC_ALPHA */
 88/* ONE_MINUS_SRC_ALPHA */
 89/* DST_ALPHA */
 90/* ONE_MINUS_DST_ALPHA */
 91
 92/* BlendEquationSeparate */
 93const GLenum FUNC_ADD = 0x8006;
 94const GLenum BLEND_EQUATION = 0x8009;
 95const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */
 96const GLenum BLEND_EQUATION_ALPHA = 0x883D;
 97
 98/* BlendSubtract */
 99const GLenum FUNC_SUBTRACT = 0x800A;
 100const GLenum FUNC_REVERSE_SUBTRACT = 0x800B;
 101
 102/* Separate Blend Functions */
 103const GLenum BLEND_DST_RGB = 0x80C8;
 104const GLenum BLEND_SRC_RGB = 0x80C9;
 105const GLenum BLEND_DST_ALPHA = 0x80CA;
 106const GLenum BLEND_SRC_ALPHA = 0x80CB;
 107const GLenum CONSTANT_COLOR = 0x8001;
 108const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002;
 109const GLenum CONSTANT_ALPHA = 0x8003;
 110const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004;
 111const GLenum BLEND_COLOR = 0x8005;
 112
 113/* Buffer Objects */
 114const GLenum ARRAY_BUFFER = 0x8892;
 115const GLenum ELEMENT_ARRAY_BUFFER = 0x8893;
 116const GLenum ARRAY_BUFFER_BINDING = 0x8894;
 117const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
 118
 119const GLenum STREAM_DRAW = 0x88E0;
 120const GLenum STATIC_DRAW = 0x88E4;
 121const GLenum DYNAMIC_DRAW = 0x88E8;
 122
 123const GLenum BUFFER_SIZE = 0x8764;
 124const GLenum BUFFER_USAGE = 0x8765;
 125
 126const GLenum CURRENT_VERTEX_ATTRIB = 0x8626;
 127
 128/* CullFaceMode */
 129const GLenum FRONT = 0x0404;
 130const GLenum BACK = 0x0405;
 131const GLenum FRONT_AND_BACK = 0x0408;
 132
 133/* DepthFunction */
 134/* NEVER */
 135/* LESS */
 136/* EQUAL */
 137/* LEQUAL */
 138/* GREATER */
 139/* NOTEQUAL */
 140/* GEQUAL */
 141/* ALWAYS */
 142
 143/* EnableCap */
 144const GLenum TEXTURE_2D = 0x0DE1;
 145const GLenum CULL_FACE = 0x0B44;
 146const GLenum BLEND = 0x0BE2;
 147const GLenum DITHER = 0x0BD0;
 148const GLenum STENCIL_TEST = 0x0B90;
 149const GLenum DEPTH_TEST = 0x0B71;
 150const GLenum SCISSOR_TEST = 0x0C11;
 151const GLenum POLYGON_OFFSET_FILL = 0x8037;
 152const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
 153const GLenum SAMPLE_COVERAGE = 0x80A0;
 154
 155/* ErrorCode */
 156const GLenum NO_ERROR = 0;
 157const GLenum INVALID_ENUM = 0x0500;
 158const GLenum INVALID_VALUE = 0x0501;
 159const GLenum INVALID_OPERATION = 0x0502;
 160const GLenum OUT_OF_MEMORY = 0x0505;
 161
 162/* FrontFaceDirection */
 163const GLenum CW = 0x0900;
 164const GLenum CCW = 0x0901;
 165
 166/* GetPName */
 167const GLenum LINE_WIDTH = 0x0B21;
 168const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D;
 169const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E;
 170const GLenum CULL_FACE_MODE = 0x0B45;
 171const GLenum FRONT_FACE = 0x0B46;
 172const GLenum DEPTH_RANGE = 0x0B70;
 173const GLenum DEPTH_WRITEMASK = 0x0B72;
 174const GLenum DEPTH_CLEAR_VALUE = 0x0B73;
 175const GLenum DEPTH_FUNC = 0x0B74;
 176const GLenum STENCIL_CLEAR_VALUE = 0x0B91;
 177const GLenum STENCIL_FUNC = 0x0B92;
 178const GLenum STENCIL_FAIL = 0x0B94;
 179const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95;
 180const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96;
 181const GLenum STENCIL_REF = 0x0B97;
 182const GLenum STENCIL_VALUE_MASK = 0x0B93;
 183const GLenum STENCIL_WRITEMASK = 0x0B98;
 184const GLenum STENCIL_BACK_FUNC = 0x8800;
 185const GLenum STENCIL_BACK_FAIL = 0x8801;
 186const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
 187const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
 188const GLenum STENCIL_BACK_REF = 0x8CA3;
 189const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4;
 190const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5;
 191const GLenum VIEWPORT = 0x0BA2;
 192const GLenum SCISSOR_BOX = 0x0C10;
 193/* SCISSOR_TEST */
 194const GLenum COLOR_CLEAR_VALUE = 0x0C22;
 195const GLenum COLOR_WRITEMASK = 0x0C23;
 196const GLenum UNPACK_ALIGNMENT = 0x0CF5;
 197const GLenum PACK_ALIGNMENT = 0x0D05;
 198const GLenum MAX_TEXTURE_SIZE = 0x0D33;
 199const GLenum MAX_VIEWPORT_DIMS = 0x0D3A;
 200const GLenum SUBPIXEL_BITS = 0x0D50;
 201const GLenum RED_BITS = 0x0D52;
 202const GLenum GREEN_BITS = 0x0D53;
 203const GLenum BLUE_BITS = 0x0D54;
 204const GLenum ALPHA_BITS = 0x0D55;
 205const GLenum DEPTH_BITS = 0x0D56;
 206const GLenum STENCIL_BITS = 0x0D57;
 207const GLenum POLYGON_OFFSET_UNITS = 0x2A00;
 208/* POLYGON_OFFSET_FILL */
 209const GLenum POLYGON_OFFSET_FACTOR = 0x8038;
 210const GLenum TEXTURE_BINDING_2D = 0x8069;
 211const GLenum SAMPLE_BUFFERS = 0x80A8;
 212const GLenum SAMPLES = 0x80A9;
 213const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA;
 214const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB;
 215
 216/* GetTextureParameter */
 217/* TEXTURE_MAG_FILTER */
 218/* TEXTURE_MIN_FILTER */
 219/* TEXTURE_WRAP_S */
 220/* TEXTURE_WRAP_T */
 221
 222const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3;
 223
 224/* HintMode */
 225const GLenum DONT_CARE = 0x1100;
 226const GLenum FASTEST = 0x1101;
 227const GLenum NICEST = 0x1102;
 228
 229/* HintTarget */
 230const GLenum GENERATE_MIPMAP_HINT = 0x8192;
 231
 232/* DataType */
 233const GLenum BYTE = 0x1400;
 234const GLenum UNSIGNED_BYTE = 0x1401;
 235const GLenum SHORT = 0x1402;
 236const GLenum UNSIGNED_SHORT = 0x1403;
 237const GLenum INT = 0x1404;
 238const GLenum UNSIGNED_INT = 0x1405;
 239const GLenum FLOAT = 0x1406;
 240
 241/* PixelFormat */
 242const GLenum DEPTH_COMPONENT = 0x1902;
 243const GLenum ALPHA = 0x1906;
 244const GLenum RGB = 0x1907;
 245const GLenum RGBA = 0x1908;
 246const GLenum LUMINANCE = 0x1909;
 247const GLenum LUMINANCE_ALPHA = 0x190A;
 248
 249/* PixelType */
 250/* UNSIGNED_BYTE */
 251const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033;
 252const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034;
 253const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363;
 254
 255/* Shaders */
 256const GLenum FRAGMENT_SHADER = 0x8B30;
 257const GLenum VERTEX_SHADER = 0x8B31;
 258const GLenum MAX_VERTEX_ATTRIBS = 0x8869;
 259const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
 260const GLenum MAX_VARYING_VECTORS = 0x8DFC;
 261const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
 262const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
 263const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872;
 264const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
 265const GLenum SHADER_TYPE = 0x8B4F;
 266const GLenum DELETE_STATUS = 0x8B80;
 267const GLenum LINK_STATUS = 0x8B82;
 268const GLenum VALIDATE_STATUS = 0x8B83;
 269const GLenum ATTACHED_SHADERS = 0x8B85;
 270const GLenum ACTIVE_UNIFORMS = 0x8B86;
 271const GLenum ACTIVE_ATTRIBUTES = 0x8B89;
 272const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C;
 273const GLenum CURRENT_PROGRAM = 0x8B8D;
 274
 275/* StencilFunction */
 276const GLenum NEVER = 0x0200;
 277const GLenum LESS = 0x0201;
 278const GLenum EQUAL = 0x0202;
 279const GLenum LEQUAL = 0x0203;
 280const GLenum GREATER = 0x0204;
 281const GLenum NOTEQUAL = 0x0205;
 282const GLenum GEQUAL = 0x0206;
 283const GLenum ALWAYS = 0x0207;
 284
 285/* StencilOp */
 286/* ZERO */
 287const GLenum KEEP = 0x1E00;
 288const GLenum REPLACE = 0x1E01;
 289const GLenum INCR = 0x1E02;
 290const GLenum DECR = 0x1E03;
 291const GLenum INVERT = 0x150A;
 292const GLenum INCR_WRAP = 0x8507;
 293const GLenum DECR_WRAP = 0x8508;
 294
 295/* StringName */
 296const GLenum VENDOR = 0x1F00;
 297const GLenum RENDERER = 0x1F01;
 298const GLenum VERSION = 0x1F02;
 299
 300/* TextureMagFilter */
 301const GLenum NEAREST = 0x2600;
 302const GLenum LINEAR = 0x2601;
 303
 304/* TextureMinFilter */
 305/* NEAREST */
 306/* LINEAR */
 307const GLenum NEAREST_MIPMAP_NEAREST = 0x2700;
 308const GLenum LINEAR_MIPMAP_NEAREST = 0x2701;
 309const GLenum NEAREST_MIPMAP_LINEAR = 0x2702;
 310const GLenum LINEAR_MIPMAP_LINEAR = 0x2703;
 311
 312/* TextureParameterName */
 313const GLenum TEXTURE_MAG_FILTER = 0x2800;
 314const GLenum TEXTURE_MIN_FILTER = 0x2801;
 315const GLenum TEXTURE_WRAP_S = 0x2802;
 316const GLenum TEXTURE_WRAP_T = 0x2803;
 317
 318/* TextureTarget */
 319/* TEXTURE_2D */
 320const GLenum TEXTURE = 0x1702;
 321
 322const GLenum TEXTURE_CUBE_MAP = 0x8513;
 323const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514;
 324const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
 325const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
 326const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
 327const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
 328const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
 329const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
 330const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
 331
 332/* TextureUnit */
 333const GLenum TEXTURE0 = 0x84C0;
 334const GLenum TEXTURE1 = 0x84C1;
 335const GLenum TEXTURE2 = 0x84C2;
 336const GLenum TEXTURE3 = 0x84C3;
 337const GLenum TEXTURE4 = 0x84C4;
 338const GLenum TEXTURE5 = 0x84C5;
 339const GLenum TEXTURE6 = 0x84C6;
 340const GLenum TEXTURE7 = 0x84C7;
 341const GLenum TEXTURE8 = 0x84C8;
 342const GLenum TEXTURE9 = 0x84C9;
 343const GLenum TEXTURE10 = 0x84CA;
 344const GLenum TEXTURE11 = 0x84CB;
 345const GLenum TEXTURE12 = 0x84CC;
 346const GLenum TEXTURE13 = 0x84CD;
 347const GLenum TEXTURE14 = 0x84CE;
 348const GLenum TEXTURE15 = 0x84CF;
 349const GLenum TEXTURE16 = 0x84D0;
 350const GLenum TEXTURE17 = 0x84D1;
 351const GLenum TEXTURE18 = 0x84D2;
 352const GLenum TEXTURE19 = 0x84D3;
 353const GLenum TEXTURE20 = 0x84D4;
 354const GLenum TEXTURE21 = 0x84D5;
 355const GLenum TEXTURE22 = 0x84D6;
 356const GLenum TEXTURE23 = 0x84D7;
 357const GLenum TEXTURE24 = 0x84D8;
 358const GLenum TEXTURE25 = 0x84D9;
 359const GLenum TEXTURE26 = 0x84DA;
 360const GLenum TEXTURE27 = 0x84DB;
 361const GLenum TEXTURE28 = 0x84DC;
 362const GLenum TEXTURE29 = 0x84DD;
 363const GLenum TEXTURE30 = 0x84DE;
 364const GLenum TEXTURE31 = 0x84DF;
 365const GLenum ACTIVE_TEXTURE = 0x84E0;
 366
 367/* TextureWrapMode */
 368const GLenum REPEAT = 0x2901;
 369const GLenum CLAMP_TO_EDGE = 0x812F;
 370const GLenum MIRRORED_REPEAT = 0x8370;
 371
 372/* Uniform Types */
 373const GLenum FLOAT_VEC2 = 0x8B50;
 374const GLenum FLOAT_VEC3 = 0x8B51;
 375const GLenum FLOAT_VEC4 = 0x8B52;
 376const GLenum INT_VEC2 = 0x8B53;
 377const GLenum INT_VEC3 = 0x8B54;
 378const GLenum INT_VEC4 = 0x8B55;
 379const GLenum BOOL = 0x8B56;
 380const GLenum BOOL_VEC2 = 0x8B57;
 381const GLenum BOOL_VEC3 = 0x8B58;
 382const GLenum BOOL_VEC4 = 0x8B59;
 383const GLenum FLOAT_MAT2 = 0x8B5A;
 384const GLenum FLOAT_MAT3 = 0x8B5B;
 385const GLenum FLOAT_MAT4 = 0x8B5C;
 386const GLenum SAMPLER_2D = 0x8B5E;
 387const GLenum SAMPLER_CUBE = 0x8B60;
 388
 389/* Vertex Arrays */
 390const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
 391const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
 392const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
 393const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
 394const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
 395const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
 396const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
 397
 398/* Shader Source */
 399const GLenum COMPILE_STATUS = 0x8B81;
 400
 401/* Shader Precision-Specified Types */
 402const GLenum LOW_FLOAT = 0x8DF0;
 403const GLenum MEDIUM_FLOAT = 0x8DF1;
 404const GLenum HIGH_FLOAT = 0x8DF2;
 405const GLenum LOW_INT = 0x8DF3;
 406const GLenum MEDIUM_INT = 0x8DF4;
 407const GLenum HIGH_INT = 0x8DF5;
 408
 409/* Framebuffer Object. */
 410const GLenum FRAMEBUFFER = 0x8D40;
 411const GLenum RENDERBUFFER = 0x8D41;
 412
 413const GLenum RGBA4 = 0x8056;
 414const GLenum RGB5_A1 = 0x8057;
 415const GLenum RGB565 = 0x8D62;
 416const GLenum DEPTH_COMPONENT16 = 0x81A5;
 417const GLenum STENCIL_INDEX = 0x1901;
 418const GLenum STENCIL_INDEX8 = 0x8D48;
 419const GLenum DEPTH_STENCIL = 0x84F9;
 420
 421const GLenum SRGB_EXT = 0x8C40;
 422const GLenum SRGB_ALPHA_EXT = 0x8C42;
 423const GLenum SRGB8_ALPHA8_EXT = 0x8C43;
 424const GLenum FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT = 0x8210;
 425
 426const GLenum MIN_EXT = 0x8007;
 427const GLenum MAX_EXT = 0x8008;
 428
 429const GLenum RENDERBUFFER_WIDTH = 0x8D42;
 430const GLenum RENDERBUFFER_HEIGHT = 0x8D43;
 431const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
 432const GLenum RENDERBUFFER_RED_SIZE = 0x8D50;
 433const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51;
 434const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52;
 435const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53;
 436const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54;
 437const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55;
 438
 439const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
 440const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
 441const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
 442const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
 443
 444const GLenum COLOR_ATTACHMENT0 = 0x8CE0;
 445const GLenum DEPTH_ATTACHMENT = 0x8D00;
 446const GLenum STENCIL_ATTACHMENT = 0x8D20;
 447const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A;
 448
 449const GLenum NONE = 0;
 450
 451const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5;
 452const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
 453const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
 454const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
 455const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
 456
 457const GLenum FRAMEBUFFER_BINDING = 0x8CA6;
 458const GLenum RENDERBUFFER_BINDING = 0x8CA7;
 459const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8;
 460
 461const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506;
 462
 463/* WebGL-specific enums */
 464const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240;
 465const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
 466const GLenum CONTEXT_LOST_WEBGL = 0x9242;
 467const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
 468const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
 469
 470readonly attribute GLsizei drawingBufferWidth;
 471readonly attribute GLsizei drawingBufferHeight;
 472
 473[StrictTypeChecking, RaisesException] void activeTexture(GLenum texture);
 474[StrictTypeChecking, RaisesException] void attachShader(WebGLProgram program, WebGLShader shader);
 475[StrictTypeChecking, RaisesException] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name);
 476[StrictTypeChecking, RaisesException] void bindBuffer(GLenum target, WebGLBuffer buffer);
 477[StrictTypeChecking, RaisesException] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer);
 478[StrictTypeChecking, RaisesException] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer);
 479[StrictTypeChecking, RaisesException] void bindTexture(GLenum target, WebGLTexture texture);
 480[StrictTypeChecking] void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 481[StrictTypeChecking] void blendEquation(GLenum mode);
 482[StrictTypeChecking] void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
 483[StrictTypeChecking] void blendFunc(GLenum sfactor, GLenum dfactor);
 484[StrictTypeChecking] void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
 485[StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
 486[StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage);
 487[StrictTypeChecking, RaisesException] void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
 488[StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data);
 489[StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView? data);
 490
 491[StrictTypeChecking] GLenum checkFramebufferStatus(GLenum target);
 492[StrictTypeChecking] void clear(GLbitfield mask);
 493[StrictTypeChecking] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 494[StrictTypeChecking] void clearDepth(GLclampf depth);
 495[StrictTypeChecking] void clearStencil(GLint s);
 496[StrictTypeChecking] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 497[StrictTypeChecking, RaisesException] void compileShader(WebGLShader shader);
 498
 499[StrictTypeChecking] void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
 500GLsizei width, GLsizei height, GLint border, ArrayBufferView data);
 501[StrictTypeChecking] void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 502GLsizei width, GLsizei height, GLenum format, ArrayBufferView data);
 503
 504[StrictTypeChecking] void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
 505[StrictTypeChecking] void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 506
 507[StrictTypeChecking] WebGLBuffer createBuffer();
 508[StrictTypeChecking] WebGLFramebuffer createFramebuffer();
 509[StrictTypeChecking] WebGLProgram createProgram();
 510[StrictTypeChecking] WebGLRenderbuffer createRenderbuffer();
 511[StrictTypeChecking, RaisesException] WebGLShader createShader(GLenum type);
 512[StrictTypeChecking] WebGLTexture createTexture();
 513
 514[StrictTypeChecking] void cullFace(GLenum mode);
 515
 516[StrictTypeChecking] void deleteBuffer(WebGLBuffer buffer);
 517[StrictTypeChecking] void deleteFramebuffer(WebGLFramebuffer framebuffer);
 518[StrictTypeChecking] void deleteProgram(WebGLProgram program);
 519[StrictTypeChecking] void deleteRenderbuffer(WebGLRenderbuffer renderbuffer);
 520[StrictTypeChecking] void deleteShader(WebGLShader shader);
 521[StrictTypeChecking] void deleteTexture(WebGLTexture texture);
 522
 523[StrictTypeChecking] void depthFunc(GLenum func);
 524[StrictTypeChecking] void depthMask(GLboolean flag);
 525[StrictTypeChecking] void depthRange(GLclampf zNear, GLclampf zFar);
 526[StrictTypeChecking, RaisesException] void detachShader(WebGLProgram program, WebGLShader shader);
 527[StrictTypeChecking] void disable(GLenum cap);
 528[StrictTypeChecking, RaisesException] void disableVertexAttribArray(GLuint index);
 529[StrictTypeChecking, RaisesException] void drawArrays(GLenum mode, GLint first, GLsizei count);
 530[StrictTypeChecking, RaisesException] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset);
 531
 532[StrictTypeChecking] void enable(GLenum cap);
 533[StrictTypeChecking, RaisesException] void enableVertexAttribArray(GLuint index);
 534[StrictTypeChecking] void finish();
 535[StrictTypeChecking] void flush();
 536[StrictTypeChecking, RaisesException] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer);
 537[StrictTypeChecking, RaisesException] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level);
 538[StrictTypeChecking] void frontFace(GLenum mode);
 539[StrictTypeChecking] void generateMipmap(GLenum target);
 540
 541[StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index);
 542[StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index);
 543
 544[StrictTypeChecking, Custom, RaisesException] void getAttachedShaders(WebGLProgram program);
 545
 546[StrictTypeChecking] GLint getAttribLocation(WebGLProgram program, DOMString name);
 547
 548[StrictTypeChecking, Custom] any getBufferParameter(GLenum target, GLenum pname);
 549
 550[StrictTypeChecking] WebGLContextAttributes getContextAttributes();
 551
 552[StrictTypeChecking] GLenum getError();
 553
 554// object getExtension(DOMString name);
 555[StrictTypeChecking, Custom] any getExtension(DOMString name);
 556
 557[StrictTypeChecking, Custom, RaisesException] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname);
 558[StrictTypeChecking, Custom, RaisesException] any getParameter(GLenum pname);
 559[StrictTypeChecking, Custom, RaisesException] any getProgramParameter(WebGLProgram program, GLenum pname);
 560[StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getProgramInfoLog(WebGLProgram program);
 561[StrictTypeChecking, Custom, RaisesException] any getRenderbufferParameter(GLenum target, GLenum pname);
 562[StrictTypeChecking, Custom, RaisesException] any getShaderParameter(WebGLShader shader, GLenum pname);
 563
 564[StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderInfoLog(WebGLShader shader);
 565
 566[StrictTypeChecking, RaisesException] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
 567
 568[StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderSource(WebGLShader shader);
 569
 570[StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions();
 571
 572[StrictTypeChecking, Custom, RaisesException] any getTexParameter(GLenum target, GLenum pname);
 573
 574[StrictTypeChecking, Custom, RaisesException] any getUniform(WebGLProgram program, WebGLUniformLocation location);
 575
 576[StrictTypeChecking, RaisesException] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name);
 577
 578[StrictTypeChecking, Custom, RaisesException] any getVertexAttrib(GLuint index, GLenum pname);
 579
 580[StrictTypeChecking] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
 581
 582[StrictTypeChecking] void hint(GLenum target, GLenum mode);
 583[StrictTypeChecking] GLboolean isBuffer(WebGLBuffer buffer);
 584[StrictTypeChecking] GLboolean isContextLost();
 585[StrictTypeChecking] GLboolean isEnabled(GLenum cap);
 586[StrictTypeChecking] GLboolean isFramebuffer(WebGLFramebuffer framebuffer);
 587[StrictTypeChecking] GLboolean isProgram(WebGLProgram program);
 588[StrictTypeChecking] GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer);
 589[StrictTypeChecking] GLboolean isShader(WebGLShader shader);
 590[StrictTypeChecking] GLboolean isTexture(WebGLTexture texture);
 591[StrictTypeChecking] void lineWidth(GLfloat width);
 592[StrictTypeChecking, RaisesException] void linkProgram(WebGLProgram program);
 593[StrictTypeChecking] void pixelStorei(GLenum pname, GLint param);
 594[StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units);
 595
 596[StrictTypeChecking, RaisesException] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels);
 597
 598[StrictTypeChecking] void releaseShaderCompiler();
 599[StrictTypeChecking] void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
 600[StrictTypeChecking] void sampleCoverage(GLclampf value, GLboolean invert);
 601[StrictTypeChecking] void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
 602[StrictTypeChecking, RaisesException] void shaderSource(WebGLShader shader, DOMString string);
 603[StrictTypeChecking] void stencilFunc(GLenum func, GLint ref, GLuint mask);
 604[StrictTypeChecking] void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
 605[StrictTypeChecking] void stencilMask(GLuint mask);
 606[StrictTypeChecking] void stencilMaskSeparate(GLenum face, GLuint mask);
 607[StrictTypeChecking] void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
 608[StrictTypeChecking] void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
 609
 610[StrictTypeChecking] void texParameterf(GLenum target, GLenum pname, GLfloat param);
 611[StrictTypeChecking] void texParameteri(GLenum target, GLenum pname, GLint param);
 612
 613// Supported forms:
 614[StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
 615GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
 616[StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 617GLenum format, GLenum type, ImageData? pixels);
 618[StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 619GLenum format, GLenum type, HTMLImageElement? image);
 620[StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 621GLenum format, GLenum type, HTMLCanvasElement? canvas);
 622#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
 623[StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat,
 624GLenum format, GLenum type, HTMLVideoElement? video);
 625#endif
 626
 627[StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 628GLsizei width, GLsizei height,
 629GLenum format, GLenum type, ArrayBufferView? pixels);
 630[StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 631GLenum format, GLenum type, ImageData? pixels);
 632[StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 633GLenum format, GLenum type, HTMLImageElement? image);
 634[StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 635GLenum format, GLenum type, HTMLCanvasElement? canvas);
 636#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
 637[StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
 638GLenum format, GLenum type, HTMLVideoElement? video);
 639#endif
 640
 641[StrictTypeChecking, RaisesException] void uniform1f(WebGLUniformLocation location, GLfloat x);
 642[StrictTypeChecking, Custom, RaisesException] void uniform1fv(WebGLUniformLocation location, Float32Array v);
 643[StrictTypeChecking, RaisesException] void uniform1i(WebGLUniformLocation location, GLint x);
 644[StrictTypeChecking, Custom, RaisesException] void uniform1iv(WebGLUniformLocation location, Int32Array v);
 645[StrictTypeChecking, RaisesException] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y);
 646[StrictTypeChecking, Custom, RaisesException] void uniform2fv(WebGLUniformLocation location, Float32Array v);
 647[StrictTypeChecking, RaisesException] void uniform2i(WebGLUniformLocation location, GLint x, GLint y);
 648[StrictTypeChecking, Custom, RaisesException] void uniform2iv(WebGLUniformLocation location, Int32Array v);
 649[StrictTypeChecking, RaisesException] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z);
 650[StrictTypeChecking, Custom, RaisesException] void uniform3fv(WebGLUniformLocation location, Float32Array v);
 651[StrictTypeChecking, RaisesException] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z);
 652[StrictTypeChecking, Custom, RaisesException] void uniform3iv(WebGLUniformLocation location, Int32Array v);
 653[StrictTypeChecking, RaisesException] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 654[StrictTypeChecking, Custom, RaisesException] void uniform4fv(WebGLUniformLocation location, Float32Array v);
 655[StrictTypeChecking, RaisesException] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w);
 656[StrictTypeChecking, Custom, RaisesException] void uniform4iv(WebGLUniformLocation location, Int32Array v);
 657
 658[StrictTypeChecking, Custom, RaisesException] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
 659[StrictTypeChecking, Custom, RaisesException] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
 660[StrictTypeChecking, Custom, RaisesException] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array);
 661
 662[StrictTypeChecking, RaisesException] void useProgram(WebGLProgram program);
 663[StrictTypeChecking, RaisesException] void validateProgram(WebGLProgram program);
 664
 665[StrictTypeChecking] void vertexAttrib1f(GLuint indx, GLfloat x);
 666[StrictTypeChecking, Custom] void vertexAttrib1fv(GLuint indx, Float32Array values);
 667[StrictTypeChecking] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
 668[StrictTypeChecking, Custom] void vertexAttrib2fv(GLuint indx, Float32Array values);
 669[StrictTypeChecking] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
 670[StrictTypeChecking, Custom] void vertexAttrib3fv(GLuint indx, Float32Array values);
 671[StrictTypeChecking] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 672[StrictTypeChecking, Custom] void vertexAttrib4fv(GLuint indx, Float32Array values);
 673[StrictTypeChecking, RaisesException] void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized,
 674GLsizei stride, GLintptr offset);
 675
 676[StrictTypeChecking] void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 677};
0

Source/WebCore/html/canvas/WebGLShader.cpp

3030#include "WebGLShader.h"
3131
3232#include "WebGLContextGroup.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContext* ctx, GC3Denum type)
 37PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContextBase* ctx, GC3Denum type)
3838{
3939 return adoptRef(new WebGLShader(ctx, type));
4040}
4141
42 WebGLShader::WebGLShader(WebGLRenderingContext* ctx, GC3Denum type)
 42WebGLShader::WebGLShader(WebGLRenderingContextBase* ctx, GC3Denum type)
4343 : WebGLSharedObject(ctx)
4444 , m_type(type)
4545 , m_source("")
178372

Source/WebCore/html/canvas/WebGLShader.h

@@class WebGLShader final : public WebGLSh
3636public:
3737 virtual ~WebGLShader();
3838
39  static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GC3Denum);
 39 static PassRefPtr<WebGLShader> create(WebGLRenderingContextBase*, GC3Denum);
4040
4141 GC3Denum getType() const { return m_type; }
4242 const String& getSource() const { return m_source; }

@@public:
4747 void setValid(bool valid) { m_isValid = valid; }
4848
4949private:
50  WebGLShader(WebGLRenderingContext*, GC3Denum);
 50 WebGLShader(WebGLRenderingContextBase*, GC3Denum);
5151
5252 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
5353
178372

Source/WebCore/html/canvas/WebGLSharedObject.cpp

3030#include "WebGLSharedObject.h"
3131
3232#include "WebGLContextGroup.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context)
 37WebGLSharedObject::WebGLSharedObject(WebGLRenderingContextBase* context)
3838 : WebGLObject(context),
3939 m_contextGroup(context->contextGroup())
4040{
178372

Source/WebCore/html/canvas/WebGLSharedObject.h

@@namespace WebCore {
3232
3333class GraphicsContext3D;
3434class WebGLContextGroup;
35 class WebGLRenderingContext;
 35class WebGLRenderingContextBase;
3636
3737// WebGLSharedObject the base class for objects that can be shared by multiple
3838// WebGLRenderingContexts.

@@public:
4848 virtual bool isShader() const { return false; }
4949 virtual bool isTexture() const { return false; }
5050
51  virtual bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContext*) const override
 51 virtual bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContextBase*) const override
5252 {
5353 return contextGroup == m_contextGroup;
5454 }

@@public:
5656 void detachContextGroup();
5757
5858protected:
59  WebGLSharedObject(WebGLRenderingContext*);
 59 WebGLSharedObject(WebGLRenderingContextBase*);
6060
6161 virtual bool hasGroupOrContext() const override
6262 {
178372

Source/WebCore/html/canvas/WebGLTexture.cpp

3131
3232#include "WebGLContextGroup.h"
3333#include "WebGLFramebuffer.h"
34 #include "WebGLRenderingContext.h"
 34#include "WebGLRenderingContextBase.h"
3535
3636namespace WebCore {
3737
38 PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx)
 38PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContextBase* ctx)
3939{
4040 return adoptRef(new WebGLTexture(ctx));
4141}
4242
43 WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx)
 43WebGLTexture::WebGLTexture(WebGLRenderingContextBase* ctx)
4444 : WebGLSharedObject(ctx)
4545 , m_target(0)
4646 , m_minFilter(GraphicsContext3D::NEAREST_MIPMAP_LINEAR)
178372

Source/WebCore/html/canvas/WebGLTexture.h

@@public:
4444
4545 virtual ~WebGLTexture();
4646
47  static PassRefPtr<WebGLTexture> create(WebGLRenderingContext*);
 47 static PassRefPtr<WebGLTexture> create(WebGLRenderingContextBase*);
4848
4949 void setTarget(GC3Denum target, GC3Dint maxLevel);
5050 void setParameteri(GC3Denum pname, GC3Dint param);

@@public:
8282 static GC3Dint computeLevelCount(GC3Dsizei width, GC3Dsizei height);
8383
8484private:
85  WebGLTexture(WebGLRenderingContext*);
 85 WebGLTexture(WebGLRenderingContextBase*);
8686
8787 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
8888
178372

Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.cpp

3030#include "WebGLVertexArrayObjectOES.h"
3131
3232#include "Extensions3D.h"
33 #include "WebGLRenderingContext.h"
 33#include "WebGLRenderingContextBase.h"
3434
3535namespace WebCore {
3636
37 PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContext* ctx, VaoType type)
 37PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContextBase* ctx, VaoType type)
3838{
3939 return adoptRef(new WebGLVertexArrayObjectOES(ctx, type));
4040}
4141
42 WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContext* ctx, VaoType type)
 42WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContextBase* ctx, VaoType type)
4343 : WebGLContextObject(ctx)
4444 , m_type(type)
4545 , m_hasEverBeenBound(false)
178372

Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.h

@@public:
4242
4343 virtual ~WebGLVertexArrayObjectOES();
4444
45  static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContext*, VaoType);
 45 static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContextBase*, VaoType);
4646
4747 // Cached values for vertex attrib range checks
4848 struct VertexAttribState {

@@public:
8989 void setVertexAttribDivisor(GC3Duint index, GC3Duint divisor);
9090
9191private:
92  WebGLVertexArrayObjectOES(WebGLRenderingContext*, VaoType);
 92 WebGLVertexArrayObjectOES(WebGLRenderingContextBase*, VaoType);
9393
9494 virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
9595
178372