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