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