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#ifndef ANDROID_HWUI_RENDER_BUFFER_H
18#define ANDROID_HWUI_RENDER_BUFFER_H
19
20#include <GLES2/gl2.h>
21#include <GLES2/gl2ext.h>
22
23namespace android {
24namespace uirenderer {
25
26/**
27 * Represents an OpenGL render buffer. Render buffers are attached
28 * to layers to perform stencil work.
29 */
30struct RenderBuffer {
31    /**
32     * Creates a new render buffer in the specified format and dimensions.
33     * The format must be one of the formats allowed by glRenderbufferStorage().
34     */
35    RenderBuffer(GLenum format, uint32_t width, uint32_t height):
36        mFormat(format), mWidth(width), mHeight(height), mAllocated(false) {
37
38        glGenRenderbuffers(1, &mName);
39    }
40
41    ~RenderBuffer() {
42        if (mName) {
43            glDeleteRenderbuffers(1, &mName);
44        }
45    }
46
47    /**
48     * Returns the GL name of this render buffer.
49     */
50    GLuint getName() const {
51        return mName;
52    }
53
54    /**
55     * Returns the format of this render buffer.
56     */
57    GLenum getFormat() const {
58        return mFormat;
59    }
60
61    /**
62     * Binds this render buffer to the current GL context.
63     */
64    void bind() const {
65        glBindRenderbuffer(GL_RENDERBUFFER, mName);
66    }
67
68    /**
69     * Indicates whether this render buffer has allocated its
70     * storage. See allocate() and resize().
71     */
72    bool isAllocated() const {
73        return mAllocated;
74    }
75
76    /**
77     * Allocates this render buffer's storage if needed.
78     * This method doesn't do anything if isAllocated() returns true.
79     */
80    void allocate() {
81        if (!mAllocated) {
82            glRenderbufferStorage(GL_RENDERBUFFER, mFormat, mWidth, mHeight);
83            mAllocated = true;
84        }
85    }
86
87    /**
88     * Resizes this render buffer. If the buffer was previously allocated,
89     * the storage is re-allocated wit the new specified dimensions. If the
90     * buffer wasn't previously allocated, the buffer remains unallocated.
91     */
92    void resize(uint32_t width, uint32_t height) {
93        if (isAllocated() && (width != mWidth || height != mHeight)) {
94            glRenderbufferStorage(GL_RENDERBUFFER, mFormat, width, height);
95        }
96
97        mWidth = width;
98        mHeight = height;
99    }
100
101    /**
102     * Returns the width of the render buffer in pixels.
103     */
104    uint32_t getWidth() const {
105        return mWidth;
106    }
107
108    /**
109     * Returns the height of the render buffer in pixels.
110     */
111    uint32_t getHeight() const {
112        return mHeight;
113    }
114
115    /**
116     * Returns the size of this render buffer in bytes.
117     */
118    uint32_t getSize() const {
119        // Round to the nearest byte
120        return (uint32_t) ((mWidth * mHeight * formatSize(mFormat)) / 8.0f + 0.5f);
121    }
122
123    /**
124     * Returns the number of bits per component in the specified format.
125     * The format must be one of the formats allowed by glRenderbufferStorage().
126     */
127    static uint32_t formatSize(GLenum format) {
128        switch (format) {
129            case GL_STENCIL_INDEX8:
130                return 8;
131            case GL_STENCIL_INDEX1_OES:
132                return 1;
133            case GL_STENCIL_INDEX4_OES:
134                return 4;
135            case GL_DEPTH_COMPONENT16:
136            case GL_RGBA4:
137            case GL_RGB565:
138            case GL_RGB5_A1:
139                return 16;
140        }
141        return 0;
142    }
143
144    /**
145     * Indicates whether the specified format represents a stencil buffer.
146     */
147    static bool isStencilBuffer(GLenum format) {
148        switch (format) {
149            case GL_STENCIL_INDEX8:
150            case GL_STENCIL_INDEX1_OES:
151            case GL_STENCIL_INDEX4_OES:
152                return true;
153        }
154        return false;
155    }
156
157    /**
158     * Returns the name of the specified render buffer format.
159     */
160    static const char* formatName(GLenum format) {
161        switch (format) {
162            case GL_STENCIL_INDEX8:
163                return "STENCIL_8";
164            case GL_STENCIL_INDEX1_OES:
165                return "STENCIL_1";
166            case GL_STENCIL_INDEX4_OES:
167                return "STENCIL_4";
168            case GL_DEPTH_COMPONENT16:
169                return "DEPTH_16";
170            case GL_RGBA4:
171                return "RGBA_4444";
172            case GL_RGB565:
173                return "RGB_565";
174            case GL_RGB5_A1:
175                return "RGBA_5551";
176        }
177        return "Unknown";
178    }
179
180private:
181    GLenum mFormat;
182
183    uint32_t mWidth;
184    uint32_t mHeight;
185
186    bool mAllocated;
187
188    GLuint mName;
189}; // struct RenderBuffer
190
191}; // namespace uirenderer
192}; // namespace android
193
194#endif // ANDROID_HWUI_RENDER_BUFFER_H
195