blob: 96247260f0f423a1d62abc607b434b841e481788 [file] [log] [blame]
Romain Guycf51a412013-04-08 19:40:31 -07001/*
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
Chris Craik96a5c4c2015-01-27 15:46:35 -080017#include "PixelBuffer.h"
Romain Guycf51a412013-04-08 19:40:31 -070018
Romain Guy9e6f3ac2013-06-20 16:31:35 -070019#include "Debug.h"
Romain Guycf51a412013-04-08 19:40:31 -070020#include "Extensions.h"
Romain Guycf51a412013-04-08 19:40:31 -070021#include "Properties.h"
Chris Craik96a5c4c2015-01-27 15:46:35 -080022#include "renderstate/RenderState.h"
23
24#include <utils/Log.h>
Romain Guycf51a412013-04-08 19:40:31 -070025
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);
Romain Guycf51a412013-04-08 19:40:31 -070036
Chris Craikd41c4d82015-01-05 15:51:13 -080037 uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
38 void unmap() override;
Romain Guycf51a412013-04-08 19:40:31 -070039
Chris Craikd41c4d82015-01-05 15:51:13 -080040 uint8_t* getMappedPointer() const override;
Romain Guycf51a412013-04-08 19:40:31 -070041
Chris Craikd41c4d82015-01-05 15:51:13 -080042 void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
Romain Guycf51a412013-04-08 19:40:31 -070043
44private:
Chris Craik51d6a3d2014-12-22 17:16:56 -080045 std::unique_ptr<uint8_t[]> mBuffer;
Romain Guycf51a412013-04-08 19:40:31 -070046};
47
Chris Craik51d6a3d2014-12-22 17:16:56 -080048CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
49 : PixelBuffer(format, width, height)
50 , mBuffer(new uint8_t[width * height * formatSize(format)]) {
Romain Guycf51a412013-04-08 19:40:31 -070051}
52
53uint8_t* CpuPixelBuffer::map(AccessMode mode) {
54 if (mAccessMode == kAccessMode_None) {
55 mAccessMode = mode;
56 }
Chris Craik51d6a3d2014-12-22 17:16:56 -080057 return mBuffer.get();
Romain Guycf51a412013-04-08 19:40:31 -070058}
59
60void CpuPixelBuffer::unmap() {
61 mAccessMode = kAccessMode_None;
62}
63
64uint8_t* CpuPixelBuffer::getMappedPointer() const {
Chris Craik51d6a3d2014-12-22 17:16:56 -080065 return mAccessMode == kAccessMode_None ? nullptr : mBuffer.get();
Romain Guycf51a412013-04-08 19:40:31 -070066}
67
68void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
69 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
Chris Craik51d6a3d2014-12-22 17:16:56 -080070 mFormat, GL_UNSIGNED_BYTE, &mBuffer[offset]);
Romain Guycf51a412013-04-08 19:40:31 -070071}
72
73///////////////////////////////////////////////////////////////////////////////
74// GPU pixel buffer
75///////////////////////////////////////////////////////////////////////////////
76
77class GpuPixelBuffer: public PixelBuffer {
78public:
79 GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
80 ~GpuPixelBuffer();
81
Chris Craikd41c4d82015-01-05 15:51:13 -080082 uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
83 void unmap() override;
Romain Guycf51a412013-04-08 19:40:31 -070084
Chris Craikd41c4d82015-01-05 15:51:13 -080085 uint8_t* getMappedPointer() const override;
Romain Guycf51a412013-04-08 19:40:31 -070086
Chris Craikd41c4d82015-01-05 15:51:13 -080087 void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
Romain Guycf51a412013-04-08 19:40:31 -070088
89private:
90 GLuint mBuffer;
91 uint8_t* mMappedPointer;
92 Caches& mCaches;
93};
94
Chris Craik96a5c4c2015-01-27 15:46:35 -080095GpuPixelBuffer::GpuPixelBuffer(GLenum format,
96 uint32_t width, uint32_t height)
Chris Craikd41c4d82015-01-05 15:51:13 -080097 : PixelBuffer(format, width, height)
98 , mMappedPointer(nullptr)
Chris Craik96a5c4c2015-01-27 15:46:35 -080099 , mCaches(Caches::getInstance()){
Romain Guycf51a412013-04-08 19:40:31 -0700100 glGenBuffers(1, &mBuffer);
Chris Craik96a5c4c2015-01-27 15:46:35 -0800101
Chris Craik44eb2c02015-01-29 09:45:09 -0800102 mCaches.pixelBufferState().bind(mBuffer);
Chris Craikd41c4d82015-01-05 15:51:13 -0800103 glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
Chris Craik44eb2c02015-01-29 09:45:09 -0800104 mCaches.pixelBufferState().unbind();
Romain Guycf51a412013-04-08 19:40:31 -0700105}
106
107GpuPixelBuffer::~GpuPixelBuffer() {
108 glDeleteBuffers(1, &mBuffer);
109}
110
111uint8_t* GpuPixelBuffer::map(AccessMode mode) {
112 if (mAccessMode == kAccessMode_None) {
Chris Craik44eb2c02015-01-29 09:45:09 -0800113 mCaches.pixelBufferState().bind(mBuffer);
Romain Guycf51a412013-04-08 19:40:31 -0700114 mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
Romain Guy9e6f3ac2013-06-20 16:31:35 -0700115#if DEBUG_OPENGL
116 if (!mMappedPointer) {
117 GLenum status = GL_NO_ERROR;
118 while ((status = glGetError()) != GL_NO_ERROR) {
119 ALOGE("Could not map GPU pixel buffer: 0x%x", status);
120 }
121 }
122#endif
Romain Guycf51a412013-04-08 19:40:31 -0700123 mAccessMode = mode;
124 }
125
126 return mMappedPointer;
127}
128
129void GpuPixelBuffer::unmap() {
130 if (mAccessMode != kAccessMode_None) {
131 if (mMappedPointer) {
Chris Craik44eb2c02015-01-29 09:45:09 -0800132 mCaches.pixelBufferState().bind(mBuffer);
Romain Guy03c00b52013-06-20 18:30:28 -0700133 GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
134 if (status == GL_FALSE) {
135 ALOGE("Corrupted GPU pixel buffer");
136 }
Romain Guycf51a412013-04-08 19:40:31 -0700137 }
138 mAccessMode = kAccessMode_None;
Chris Craikd41c4d82015-01-05 15:51:13 -0800139 mMappedPointer = nullptr;
Romain Guycf51a412013-04-08 19:40:31 -0700140 }
141}
142
143uint8_t* GpuPixelBuffer::getMappedPointer() const {
144 return mMappedPointer;
145}
146
147void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
148 // If the buffer is not mapped, unmap() will not bind it
Chris Craik44eb2c02015-01-29 09:45:09 -0800149 mCaches.pixelBufferState().bind(mBuffer);
Romain Guycf51a412013-04-08 19:40:31 -0700150 unmap();
151 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
Kévin PETIT73fc5582014-02-13 11:03:40 +0000152 GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
Romain Guycf51a412013-04-08 19:40:31 -0700153}
154
155///////////////////////////////////////////////////////////////////////////////
156// Factory
157///////////////////////////////////////////////////////////////////////////////
158
Chris Craik96a5c4c2015-01-27 15:46:35 -0800159PixelBuffer* PixelBuffer::create(GLenum format,
160 uint32_t width, uint32_t height, BufferType type) {
Romain Guyf9f00162013-05-09 11:50:12 -0700161 if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
162 return new GpuPixelBuffer(format, width, height);
Romain Guycf51a412013-04-08 19:40:31 -0700163 }
164 return new CpuPixelBuffer(format, width, height);
165}
166
167}; // namespace uirenderer
168}; // namespace android