• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 namespace android {
28 namespace uirenderer {
29 
30 ///////////////////////////////////////////////////////////////////////////////
31 // CPU pixel buffer
32 ///////////////////////////////////////////////////////////////////////////////
33 
34 class CpuPixelBuffer: public PixelBuffer {
35 public:
36     CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
37     ~CpuPixelBuffer();
38 
39     uint8_t* map(AccessMode mode = kAccessMode_ReadWrite);
40     void unmap();
41 
42     uint8_t* getMappedPointer() const;
43 
44     void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset);
45 
46 private:
47     uint8_t* mBuffer;
48 };
49 
CpuPixelBuffer(GLenum format,uint32_t width,uint32_t height)50 CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height):
51         PixelBuffer(format, width, height) {
52     mBuffer = new uint8_t[width * height * formatSize(format)];
53 }
54 
~CpuPixelBuffer()55 CpuPixelBuffer::~CpuPixelBuffer() {
56     delete[] mBuffer;
57 }
58 
map(AccessMode mode)59 uint8_t* CpuPixelBuffer::map(AccessMode mode) {
60     if (mAccessMode == kAccessMode_None) {
61         mAccessMode = mode;
62     }
63     return mBuffer;
64 }
65 
unmap()66 void CpuPixelBuffer::unmap() {
67     mAccessMode = kAccessMode_None;
68 }
69 
getMappedPointer() const70 uint8_t* CpuPixelBuffer::getMappedPointer() const {
71     return mAccessMode == kAccessMode_None ? NULL : mBuffer;
72 }
73 
upload(uint32_t x,uint32_t y,uint32_t width,uint32_t height,int offset)74 void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
75     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
76             mFormat, GL_UNSIGNED_BYTE, mBuffer + offset);
77 }
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 // GPU pixel buffer
81 ///////////////////////////////////////////////////////////////////////////////
82 
83 class GpuPixelBuffer: public PixelBuffer {
84 public:
85     GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
86     ~GpuPixelBuffer();
87 
88     uint8_t* map(AccessMode mode = kAccessMode_ReadWrite);
89     void unmap();
90 
91     uint8_t* getMappedPointer() const;
92 
93     void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset);
94 
95 private:
96     GLuint mBuffer;
97     uint8_t* mMappedPointer;
98     Caches& mCaches;
99 };
100 
GpuPixelBuffer(GLenum format,uint32_t width,uint32_t height)101 GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height):
102         PixelBuffer(format, width, height), mMappedPointer(0), mCaches(Caches::getInstance()) {
103     glGenBuffers(1, &mBuffer);
104     mCaches.bindPixelBuffer(mBuffer);
105     glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), NULL, GL_DYNAMIC_DRAW);
106     mCaches.unbindPixelBuffer();
107 }
108 
~GpuPixelBuffer()109 GpuPixelBuffer::~GpuPixelBuffer() {
110     glDeleteBuffers(1, &mBuffer);
111 }
112 
map(AccessMode mode)113 uint8_t* GpuPixelBuffer::map(AccessMode mode) {
114     if (mAccessMode == kAccessMode_None) {
115         mCaches.bindPixelBuffer(mBuffer);
116         mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
117 #if DEBUG_OPENGL
118         if (!mMappedPointer) {
119             GLenum status = GL_NO_ERROR;
120             while ((status = glGetError()) != GL_NO_ERROR) {
121                 ALOGE("Could not map GPU pixel buffer: 0x%x", status);
122             }
123         }
124 #endif
125         mAccessMode = mode;
126     }
127 
128     return mMappedPointer;
129 }
130 
unmap()131 void GpuPixelBuffer::unmap() {
132     if (mAccessMode != kAccessMode_None) {
133         if (mMappedPointer) {
134             mCaches.bindPixelBuffer(mBuffer);
135             GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
136             if (status == GL_FALSE) {
137                 ALOGE("Corrupted GPU pixel buffer");
138             }
139         }
140         mAccessMode = kAccessMode_None;
141         mMappedPointer = NULL;
142     }
143 }
144 
getMappedPointer() const145 uint8_t* GpuPixelBuffer::getMappedPointer() const {
146     return mMappedPointer;
147 }
148 
upload(uint32_t x,uint32_t y,uint32_t width,uint32_t height,int offset)149 void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
150     // If the buffer is not mapped, unmap() will not bind it
151     mCaches.bindPixelBuffer(mBuffer);
152     unmap();
153     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
154             GL_UNSIGNED_BYTE, (void*) offset);
155 }
156 
157 ///////////////////////////////////////////////////////////////////////////////
158 // Factory
159 ///////////////////////////////////////////////////////////////////////////////
160 
create(GLenum format,uint32_t width,uint32_t height,BufferType type)161 PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
162     if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
163         return new GpuPixelBuffer(format, width, height);
164     }
165     return new CpuPixelBuffer(format, width, height);
166 }
167 
168 }; // namespace uirenderer
169 }; // namespace android
170