PixelBuffer.cpp revision f9f0016b1ff816eb2c7561eed482c056189005f8
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 "Extensions.h" 23#include "PixelBuffer.h" 24#include "Properties.h" 25 26namespace android { 27namespace uirenderer { 28 29/////////////////////////////////////////////////////////////////////////////// 30// CPU pixel buffer 31/////////////////////////////////////////////////////////////////////////////// 32 33class CpuPixelBuffer: public PixelBuffer { 34public: 35 CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height); 36 ~CpuPixelBuffer(); 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 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 54CpuPixelBuffer::~CpuPixelBuffer() { 55 delete[] mBuffer; 56} 57 58uint8_t* CpuPixelBuffer::map(AccessMode mode) { 59 if (mAccessMode == kAccessMode_None) { 60 mAccessMode = mode; 61 } 62 return mBuffer; 63} 64 65void CpuPixelBuffer::unmap() { 66 mAccessMode = kAccessMode_None; 67} 68 69uint8_t* CpuPixelBuffer::getMappedPointer() const { 70 return mAccessMode == kAccessMode_None ? NULL : mBuffer; 71} 72 73void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) { 74 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, 75 mFormat, GL_UNSIGNED_BYTE, mBuffer + offset); 76} 77 78/////////////////////////////////////////////////////////////////////////////// 79// GPU pixel buffer 80/////////////////////////////////////////////////////////////////////////////// 81 82class GpuPixelBuffer: public PixelBuffer { 83public: 84 GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height); 85 ~GpuPixelBuffer(); 86 87 uint8_t* map(AccessMode mode = kAccessMode_ReadWrite); 88 void unmap(); 89 90 uint8_t* getMappedPointer() const; 91 92 void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset); 93 94private: 95 GLuint mBuffer; 96 uint8_t* mMappedPointer; 97 Caches& mCaches; 98}; 99 100GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height): 101 PixelBuffer(format, width, height), mMappedPointer(0), mCaches(Caches::getInstance()) { 102 glGenBuffers(1, &mBuffer); 103 mCaches.bindPixelBuffer(mBuffer); 104 glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), NULL, GL_DYNAMIC_DRAW); 105 mCaches.unbindPixelBuffer(); 106} 107 108GpuPixelBuffer::~GpuPixelBuffer() { 109 glDeleteBuffers(1, &mBuffer); 110} 111 112uint8_t* GpuPixelBuffer::map(AccessMode mode) { 113 if (mAccessMode == kAccessMode_None) { 114 mCaches.bindPixelBuffer(mBuffer); 115 mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode); 116 mAccessMode = mode; 117 } 118 119 return mMappedPointer; 120} 121 122void GpuPixelBuffer::unmap() { 123 if (mAccessMode != kAccessMode_None) { 124 if (mMappedPointer) { 125 mCaches.bindPixelBuffer(mBuffer); 126 glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); 127 } 128 mAccessMode = kAccessMode_None; 129 mMappedPointer = NULL; 130 } 131} 132 133uint8_t* GpuPixelBuffer::getMappedPointer() const { 134 return mMappedPointer; 135} 136 137void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) { 138 // If the buffer is not mapped, unmap() will not bind it 139 mCaches.bindPixelBuffer(mBuffer); 140 unmap(); 141 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, 142 GL_UNSIGNED_BYTE, (void*) offset); 143} 144 145/////////////////////////////////////////////////////////////////////////////// 146// Factory 147/////////////////////////////////////////////////////////////////////////////// 148 149PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) { 150 if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) { 151 return new GpuPixelBuffer(format, width, height); 152 } 153 return new CpuPixelBuffer(format, width, height); 154} 155 156}; // namespace uirenderer 157}; // namespace android 158