blob: b1bd1dc56ca6fd9283db2dae12383ce22fc94302 [file] [log] [blame]
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
* Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
#include "Extensions3DOpenGL.h"
#include "IntRect.h"
#include "IntSize.h"
#include "NotImplemented.h"
#if PLATFORM(GTK) || PLATFORM(QT)
#include "OpenGLShims.h"
#endif
namespace WebCore {
void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels)
{
const int totalBytes = m_currentWidth * m_currentHeight * 4;
::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
for (int i = 0; i < totalBytes; i += 4)
std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA.
}
bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
{
const int width = size.width();
const int height = size.height();
GLuint colorFormat = 0, pixelDataType = 0;
if (m_attrs.alpha) {
m_internalColorFormat = GL_RGBA;
colorFormat = GL_RGBA;
pixelDataType = GL_UNSIGNED_BYTE;
} else {
m_internalColorFormat = GL_RGB;
colorFormat = GL_RGB;
pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
}
// We don't allow the logic where stencil is required and depth is not.
// See GraphicsContext3D::validateAttributes.
bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil");
// Resize regular FBO.
bool mustRestoreFBO = false;
if (m_boundFBO != m_fbo) {
mustRestoreFBO = true;
::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
}
::glBindTexture(GL_TEXTURE_2D, m_texture);
::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0);
::glFramebufferTexture2DEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
::glBindTexture(GL_TEXTURE_2D, 0);
// We don't support antialiasing yet. See GraphicsContext3D::validateAttributes.
ASSERT(!m_attrs.antialias);
if (m_attrs.stencil || m_attrs.depth) {
// Use a 24 bit depth buffer where we know we have it.
if (supportPackedDepthStencilBuffer) {
::glBindTexture(GL_TEXTURE_2D, m_depthStencilBuffer);
::glTexImage2D(GL_TEXTURE_2D, 0, GraphicsContext3D::DEPTH_STENCIL, width, height, 0, GraphicsContext3D::DEPTH_STENCIL, GraphicsContext3D::UNSIGNED_INT_24_8, 0);
if (m_attrs.stencil)
::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0);
if (m_attrs.depth)
::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0);
::glBindTexture(GL_TEXTURE_2D, 0);
} else {
if (m_attrs.stencil) {
::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer);
::glRenderbufferStorageEXT(GraphicsContext3D::RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
::glFramebufferRenderbufferEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer);
}
if (m_attrs.depth) {
::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
::glRenderbufferStorageEXT(GraphicsContext3D::RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
::glFramebufferRenderbufferEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
}
::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, 0);
}
}
if (glCheckFramebufferStatusEXT(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
// FIXME: cleanup
notImplemented();
}
return mustRestoreFBO;
}
void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect)
{
// FIXME: We don't support antialiasing yet.
notImplemented();
}
void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
{
makeContextCurrent();
::glRenderbufferStorageEXT(target, internalformat, width, height);
}
void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
{
makeContextCurrent();
::glGetIntegerv(pname, value);
}
void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision)
{
ASSERT(range);
ASSERT(precision);
makeContextCurrent();
::glGetShaderPrecisionFormat(shaderType, precisionType, range, precision);
}
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
{
if (width && height && !pixels) {
synthesizeGLError(INVALID_VALUE);
return false;
}
makeContextCurrent();
::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
return true;
}
void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
{
makeContextCurrent();
::glDepthRangef(zNear, zFar);
}
void GraphicsContext3D::clearDepth(GC3Dclampf depth)
{
makeContextCurrent();
::glClearDepthf(depth);
}
} // namespace WebCore
#endif // ENABLE(WEBGL)