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
34cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyclass 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)
5151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik        , mBuffer(new uint8_t[width * height * formatSize(format)]) {
52cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
53cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
54cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyuint8_t* CpuPixelBuffer::map(AccessMode mode) {
55cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    if (mAccessMode == kAccessMode_None) {
56cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mAccessMode = mode;
57cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
5851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik    return mBuffer.get();
59cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
60cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
61cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CpuPixelBuffer::unmap() {
62cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    mAccessMode = kAccessMode_None;
63cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
64cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
65cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
66cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
6751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik            mFormat, GL_UNSIGNED_BYTE, &mBuffer[offset]);
68cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
69cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
70cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
71cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy// GPU pixel buffer
72cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
73cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
74cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyclass GpuPixelBuffer: public PixelBuffer {
75cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guypublic:
76cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
77cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    ~GpuPixelBuffer();
78cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
79d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
80cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
81d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
82cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
83f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reckprotected:
84f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck    void unmap() override;
85f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck
86cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyprivate:
87cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    GLuint mBuffer;
88cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    uint8_t* mMappedPointer;
89cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    Caches& mCaches;
90cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy};
91cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
9296a5c4c7bab6718524de7253da8309143ab48befChris CraikGpuPixelBuffer::GpuPixelBuffer(GLenum format,
9396a5c4c7bab6718524de7253da8309143ab48befChris Craik        uint32_t width, uint32_t height)
94d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        : PixelBuffer(format, width, height)
95d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , mMappedPointer(nullptr)
9696a5c4c7bab6718524de7253da8309143ab48befChris Craik        , mCaches(Caches::getInstance()){
97cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    glGenBuffers(1, &mBuffer);
9896a5c4c7bab6718524de7253da8309143ab48befChris Craik
9944eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.pixelBufferState().bind(mBuffer);
100d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
10144eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.pixelBufferState().unbind();
102cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
103cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
104cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain GuyGpuPixelBuffer::~GpuPixelBuffer() {
105cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    glDeleteBuffers(1, &mBuffer);
106cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
107cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
108cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyuint8_t* GpuPixelBuffer::map(AccessMode mode) {
109cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    if (mAccessMode == kAccessMode_None) {
11044eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik        mCaches.pixelBufferState().bind(mBuffer);
111cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
1122de7771740ee08fcaff638ec6b2e460bb72fff04John Reck        if (CC_UNLIKELY(!mMappedPointer)) {
1132de7771740ee08fcaff638ec6b2e460bb72fff04John Reck            GLUtils::dumpGLErrors();
1142de7771740ee08fcaff638ec6b2e460bb72fff04John Reck            LOG_ALWAYS_FATAL("Failed to map PBO");
1159e6f3ac109b5cd7736122d1bdf83ed38b9d739c6Romain Guy        }
116cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mAccessMode = mode;
117f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck        mCaches.pixelBufferState().unbind();
118cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
119cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
120cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    return mMappedPointer;
121cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
122cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
123cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid GpuPixelBuffer::unmap() {
124cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    if (mAccessMode != kAccessMode_None) {
125cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        if (mMappedPointer) {
12644eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik            mCaches.pixelBufferState().bind(mBuffer);
12703c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy            GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
12803c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy            if (status == GL_FALSE) {
12903c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy                ALOGE("Corrupted GPU pixel buffer");
13003c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy            }
131cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        }
132cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy        mAccessMode = kAccessMode_None;
133d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        mMappedPointer = nullptr;
134cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
135cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
136cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
137cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
138cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    // If the buffer is not mapped, unmap() will not bind it
13944eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.pixelBufferState().bind(mBuffer);
140cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    unmap();
141cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
14273fc558e44be259c0833c8c8074ad2333bcb378dKévin PETIT            GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
143f3ad324a8d3f5b5530bd1945f461faf4b0adec8cJohn Reck    mCaches.pixelBufferState().unbind();
144cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
145cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
146cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
147cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy// Factory
148cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy///////////////////////////////////////////////////////////////////////////////
149cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
15096a5c4c7bab6718524de7253da8309143ab48befChris CraikPixelBuffer* PixelBuffer::create(GLenum format,
15196a5c4c7bab6718524de7253da8309143ab48befChris Craik        uint32_t width, uint32_t height, BufferType type) {
152f9f0016b1ff816eb2c7561eed482c056189005f8Romain Guy    if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
153f9f0016b1ff816eb2c7561eed482c056189005f8Romain Guy        return new GpuPixelBuffer(format, width, height);
154cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    }
155cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    return new CpuPixelBuffer(format, width, height);
156cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}
157cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
158cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}; // namespace uirenderer
159cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy}; // namespace android
160