/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "TextureImageCGL.h" #include "GLContext.h" #include "gfxQuartzSurface.h" #include "gfxPlatform.h" #include "gfxFailure.h" namespace mozilla { namespace gl { TextureImageCGL::TextureImageCGL(GLuint aTexture, const nsIntSize& aSize, GLenum aWrapMode, ContentType aContentType, GLContext* aContext, TextureImage::Flags aFlags, TextureImage::ImageFormat aImageFormat) : BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags, aImageFormat) , mPixelBuffer(0) , mPixelBufferSize(0) , mBoundPixelBuffer(false) {} TextureImageCGL::~TextureImageCGL() { if (mPixelBuffer) { mGLContext->MakeCurrent(); mGLContext->fDeleteBuffers(1, &mPixelBuffer); } } already_AddRefed TextureImageCGL::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt) { gfxIntSize size(aSize.width + 1, aSize.height + 1); mGLContext->MakeCurrent(); if (!mGLContext-> IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) { return gfxPlatform::GetPlatform()-> CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(aFmt)); } if (!mPixelBuffer) { mGLContext->fGenBuffers(1, &mPixelBuffer); } mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPixelBuffer); int32_t length = size.width * 4 * size.height; if (length > mPixelBufferSize) { mGLContext->fBufferData(LOCAL_GL_PIXEL_UNPACK_BUFFER, length, NULL, LOCAL_GL_STREAM_DRAW); mPixelBufferSize = length; } unsigned char* data = (unsigned char*)mGLContext-> fMapBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, LOCAL_GL_WRITE_ONLY); mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0); if (!data) { nsAutoCString failure; failure += "Pixel buffer binding failed: "; failure.AppendPrintf("%dx%d\n", size.width, size.height); gfx::LogFailure(failure); mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0); return gfxPlatform::GetPlatform()-> CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(aFmt)); } nsRefPtr surf = new gfxQuartzSurface(data, size, size.width * 4, aFmt); mBoundPixelBuffer = true; return surf.forget(); } bool TextureImageCGL::FinishedSurfaceUpdate() { if (mBoundPixelBuffer) { mGLContext->MakeCurrent(); mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPixelBuffer); mGLContext->fUnmapBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER); return true; } return false; } void TextureImageCGL::FinishedSurfaceUpload() { if (mBoundPixelBuffer) { mGLContext->MakeCurrent(); mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0); mBoundPixelBuffer = false; } } } }