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