1926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/* 2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 4926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * modification, are permitted provided that the following conditions 6926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * are met: 7926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 8926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 10926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * documentation and/or other materials provided with the distribution. 13926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */ 25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 26926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include "config.h" 27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/html/canvas/WebGLDrawBuffers.h" 29926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 30c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 31926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 32d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContextBase* context) 33926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : WebGLExtension(context) 34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_draw_buffers"); 36926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 37926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)WebGLDrawBuffers::~WebGLDrawBuffers() 39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)WebGLExtensionName WebGLDrawBuffers::name() const 43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return WebGLDrawBuffersName; 45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 47c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)PassRefPtrWillBeRawPtr<WebGLDrawBuffers> WebGLDrawBuffers::create(WebGLRenderingContextBase* context) 48926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 49c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return adoptRefWillBeNoop(new WebGLDrawBuffers(context)); 50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// static 53d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool WebGLDrawBuffers::supported(WebGLRenderingContextBase* context) 54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return (context->extensionsUtil()->supportsExtension("GL_EXT_draw_buffers") 56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) && satisfiesWebGLRequirements(context)); 57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)const char* WebGLDrawBuffers::extensionName() 6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return "WEBGL_draw_buffers"; 6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GLenum>& buffers) 65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 66521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (isLost()) 67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) GLsizei n = buffers.size(); 6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const GLenum* bufs = buffers.data(); 70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!m_context->m_framebufferBinding) { 71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (n != 1) { 7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer"); 73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (bufs[0] != GL_BACK && bufs[0] != GL_NONE) { 7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_context->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "BACK or NONE"); 77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0. 8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) GLenum value = (bufs[0] == GL_BACK) ? GL_COLOR_ATTACHMENT0 : GL_NONE; 81a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch m_context->webContext()->drawBuffersEXT(1, &value); 82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_context->setBackDrawBuffer(bufs[0]); 83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 8406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) if (n > m_context->maxDrawBuffers()) { 8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than max draw buffers"); 86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (GLsizei i = 0; i < n; ++i) { 8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (bufs[i] != GL_NONE && bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i)) { 9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_context->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "COLOR_ATTACHMENTi_EXT or NONE"); 91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_context->m_framebufferBinding->drawBuffers(buffers); 95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 96926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// static 99d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase* webglContext) 100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch blink::WebGraphicsContext3D* context = webglContext->webContext(); 10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Extensions3DUtil* extensionsUtil = webglContext->extensionsUtil(); 103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // This is called after we make sure GL_EXT_draw_buffers is supported. 10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) GLint maxDrawBuffers = 0; 10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) GLint maxColorAttachments = 0; 10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->getIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); 10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments); 109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (maxDrawBuffers < 4 || maxColorAttachments < 4) 110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Platform3DObject fbo = context->createFramebuffer(); 11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->bindFramebuffer(GL_FRAMEBUFFER, fbo); 114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) const unsigned char* buffer = 0; // Chromium doesn't allow init data for depth/stencil tetxures. 11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) bool supportsDepth = (extensionsUtil->supportsExtension("GL_CHROMIUM_depth_texture") 11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) || extensionsUtil->supportsExtension("GL_OES_depth_texture") 11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) || extensionsUtil->supportsExtension("GL_ARB_depth_texture")); 11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) bool supportsDepthStencil = (extensionsUtil->supportsExtension("GL_EXT_packed_depth_stencil") 12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) || extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil")); 121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Platform3DObject depthStencil = 0; 122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (supportsDepthStencil) { 123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) depthStencil = context->createTexture(); 12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->bindTexture(GL_TEXTURE_2D, depthStencil); 12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_OES, 1, 1, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, buffer); 126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Platform3DObject depth = 0; 128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (supportsDepth) { 129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) depth = context->createTexture(); 13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->bindTexture(GL_TEXTURE_2D, depth); 13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buffer); 132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Vector<Platform3DObject> colors; 135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) bool ok = true; 13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) GLint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments); 13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (GLint i = 0; i < maxAllowedBuffers; ++i) { 138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Platform3DObject color = context->createTexture(); 139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) colors.append(color); 14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->bindTexture(GL_TEXTURE_2D, color); 14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, color, 0); 14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ok = false; 145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (supportsDepth) { 14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); 14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ok = false; 151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 15309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (supportsDepthStencil) { 15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencil, 0); 15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencil, 0); 15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ok = false; 160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 16309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) webglContext->restoreCurrentFramebuffer(); 168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->deleteFramebuffer(fbo); 169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) webglContext->restoreCurrentTexture2D(); 170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (supportsDepth) 171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->deleteTexture(depth); 172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (supportsDepthStencil) 173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->deleteTexture(depthStencil); 174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (size_t i = 0; i < colors.size(); ++i) 175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->deleteTexture(colors[i]); 176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return ok; 177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 179c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 180