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
1796a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "PixelBuffer.h"
18cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
199e6f3ac109b5cd7736122d1bdf83ed38b9d739c6Romain Guy#include "Debug.h"
20cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "Extensions.h"
21cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "Properties.h"
2296a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "renderstate/RenderState.h"
232de7771740ee08fcaff638ec6b2e460bb72fff04John Reck#include "utils/GLUtils.h"
2496a5c4c7bab6718524de7253da8309143ab48befChris Craik
2596a5c4c7bab6718524de7253da8309143ab48befChris Craik#include <utils/Log.h>
26cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
27cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guynamespace android {
28cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guynamespace uirenderer {
29cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
30cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
31cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy// CPU pixel buffer
32cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
33cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckclass CpuPixelBuffer : public PixelBuffer {
35cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guypublic:
36cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
37cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
38d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
39cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
40d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
41cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
42f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reckprotected:
43f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck    void unmap() override;
44f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck
45cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyprivate:
4651d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik    std::unique_ptr<uint8_t[]> mBuffer;
47cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy};
48cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
4951d6a3db97bdd5315f1a17a4b447d10a92217b98Chris CraikCpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
5051d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik        : PixelBuffer(format, width, height)
511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        , mBuffer(new uint8_t[width * height * formatSize(format)]) {}
52cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
53cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyuint8_t* CpuPixelBuffer::map(AccessMode mode) {
54cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    if (mAccessMode == kAccessMode_None) {
55cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mAccessMode = mode;
56cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
5751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik    return mBuffer.get();
58cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
59cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
60cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CpuPixelBuffer::unmap() {
61cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    mAccessMode = kAccessMode_None;
62cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
63cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
64cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    &mBuffer[offset]);
67cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
68cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
69cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
70cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy// GPU pixel buffer
71cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
72cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckclass GpuPixelBuffer : public PixelBuffer {
74cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guypublic:
75cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
76cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    ~GpuPixelBuffer();
77cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
78d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
79cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
80d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
81cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
82f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reckprotected:
83f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck    void unmap() override;
84f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck
85cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyprivate:
86cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    GLuint mBuffer;
87cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    uint8_t* mMappedPointer;
88cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    Caches& mCaches;
89cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy};
90cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
911bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John ReckGpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
92d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        : PixelBuffer(format, width, height)
93d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , mMappedPointer(nullptr)
941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        , mCaches(Caches::getInstance()) {
95cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    glGenBuffers(1, &mBuffer);
9696a5c4c7bab6718524de7253da8309143ab48befChris Craik
9744eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.pixelBufferState().bind(mBuffer);
98d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
9944eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.pixelBufferState().unbind();
100cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
101cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
102cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain GuyGpuPixelBuffer::~GpuPixelBuffer() {
103cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    glDeleteBuffers(1, &mBuffer);
104cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
105cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
106cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyuint8_t* GpuPixelBuffer::map(AccessMode mode) {
107cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    if (mAccessMode == kAccessMode_None) {
10844eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik        mCaches.pixelBufferState().bind(mBuffer);
1091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        mMappedPointer = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
1102de7771740ee08fcaff638ec6b2e460bb72fff04John Reck        if (CC_UNLIKELY(!mMappedPointer)) {
1112de7771740ee08fcaff638ec6b2e460bb72fff04John Reck            GLUtils::dumpGLErrors();
1122de7771740ee08fcaff638ec6b2e460bb72fff04John Reck            LOG_ALWAYS_FATAL("Failed to map PBO");
1139e6f3ac109b5cd7736122d1bdf83ed38b9d739c6Romain Guy        }
114cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mAccessMode = mode;
115f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck        mCaches.pixelBufferState().unbind();
116cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
117cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
118cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    return mMappedPointer;
119cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
120cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
121cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid GpuPixelBuffer::unmap() {
122cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    if (mAccessMode != kAccessMode_None) {
123cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        if (mMappedPointer) {
12444eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik            mCaches.pixelBufferState().bind(mBuffer);
12503c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy            GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
12603c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy            if (status == GL_FALSE) {
12703c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy                ALOGE("Corrupted GPU pixel buffer");
12803c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy            }
129cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        }
130cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mAccessMode = kAccessMode_None;
131d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        mMappedPointer = nullptr;
132cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
133cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
134cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
135cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
136cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    // If the buffer is not mapped, unmap() will not bind it
13744eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.pixelBufferState().bind(mBuffer);
138cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    unmap();
1391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
1401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    reinterpret_cast<void*>(offset));
141f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck    mCaches.pixelBufferState().unbind();
142cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
143cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
144cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
145cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy// Factory
146cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
147cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
1481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John ReckPixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
149f9f0016b1ff816eb2c7561eed482c056189005f8Romain Guy    if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
150f9f0016b1ff816eb2c7561eed482c056189005f8Romain Guy        return new GpuPixelBuffer(format, width, height);
151cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
152cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    return new CpuPixelBuffer(format, width, height);
153cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
154cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
1551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace uirenderer
1561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace android
157