PixelBuffer.cpp revision 51d6a3db97bdd5315f1a17a4b447d10a92217b98
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include <utils/Log.h> 20 21#include "Caches.h" 22#include "Debug.h" 23#include "Extensions.h" 24#include "PixelBuffer.h" 25#include "Properties.h" 26 27namespace android { 28namespace uirenderer { 29 30/////////////////////////////////////////////////////////////////////////////// 31// CPU pixel buffer 32/////////////////////////////////////////////////////////////////////////////// 33 34class CpuPixelBuffer: public PixelBuffer { 35public: 36 CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height); 37 38 uint8_t* map(AccessMode mode = kAccessMode_ReadWrite); 39 void unmap(); 40 41 uint8_t* getMappedPointer() const; 42 43 void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset); 44 45private: 46 std::unique_ptr<uint8_t[]> mBuffer; 47}; 48 49CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height) 50 : PixelBuffer(format, width, height) 51 , mBuffer(new uint8_t[width * height * formatSize(format)]) { 52} 53 54uint8_t* CpuPixelBuffer::map(AccessMode mode) { 55 if (mAccessMode == kAccessMode_None) { 56 mAccessMode = mode; 57 } 58 return mBuffer.get(); 59} 60 61void CpuPixelBuffer::unmap() { 62 mAccessMode = kAccessMode_None; 63} 64 65uint8_t* CpuPixelBuffer::getMappedPointer() const { 66 return mAccessMode == kAccessMode_None ? nullptr : mBuffer.get(); 67} 68 69void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) { 70 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, 71 mFormat, GL_UNSIGNED_BYTE, &mBuffer[offset]); 72} 73 74/////////////////////////////////////////////////////////////////////////////// 75// GPU pixel buffer 76/////////////////////////////////////////////////////////////////////////////// 77 78class GpuPixelBuffer: public PixelBuffer { 79public: 80 GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height); 81 ~GpuPixelBuffer(); 82 83 uint8_t* map(AccessMode mode = kAccessMode_ReadWrite); 84 void unmap(); 85 86 uint8_t* getMappedPointer() const; 87 88 void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset); 89 90private: 91 GLuint mBuffer; 92 uint8_t* mMappedPointer; 93 Caches& mCaches; 94}; 95 96GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height): 97 PixelBuffer(format, width, height), mMappedPointer(0), mCaches(Caches::getInstance()) { 98 glGenBuffers(1, &mBuffer); 99 mCaches.bindPixelBuffer(mBuffer); 100 glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), NULL, GL_DYNAMIC_DRAW); 101 mCaches.unbindPixelBuffer(); 102} 103 104GpuPixelBuffer::~GpuPixelBuffer() { 105 glDeleteBuffers(1, &mBuffer); 106} 107 108uint8_t* GpuPixelBuffer::map(AccessMode mode) { 109 if (mAccessMode == kAccessMode_None) { 110 mCaches.bindPixelBuffer(mBuffer); 111 mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode); 112#if DEBUG_OPENGL 113 if (!mMappedPointer) { 114 GLenum status = GL_NO_ERROR; 115 while ((status = glGetError()) != GL_NO_ERROR) { 116 ALOGE("Could not map GPU pixel buffer: 0x%x", status); 117 } 118 } 119#endif 120 mAccessMode = mode; 121 } 122 123 return mMappedPointer; 124} 125 126void GpuPixelBuffer::unmap() { 127 if (mAccessMode != kAccessMode_None) { 128 if (mMappedPointer) { 129 mCaches.bindPixelBuffer(mBuffer); 130 GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); 131 if (status == GL_FALSE) { 132 ALOGE("Corrupted GPU pixel buffer"); 133 } 134 } 135 mAccessMode = kAccessMode_None; 136 mMappedPointer = NULL; 137 } 138} 139 140uint8_t* GpuPixelBuffer::getMappedPointer() const { 141 return mMappedPointer; 142} 143 144void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) { 145 // If the buffer is not mapped, unmap() will not bind it 146 mCaches.bindPixelBuffer(mBuffer); 147 unmap(); 148 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, 149 GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset)); 150} 151 152/////////////////////////////////////////////////////////////////////////////// 153// Factory 154/////////////////////////////////////////////////////////////////////////////// 155 156PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) { 157 if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) { 158 return new GpuPixelBuffer(format, width, height); 159 } 160 return new CpuPixelBuffer(format, width, height); 161} 162 163}; // namespace uirenderer 164}; // namespace android 165