Tizen 2.1 base
[sdk/emulator/qemu.git] / hw / yagl_apis / gles / yagl_gles_framebuffer.c
1 #include <GL/gl.h>
2 #include "yagl_gles_framebuffer.h"
3 #include "yagl_gles_renderbuffer.h"
4 #include "yagl_gles_texture.h"
5 #include "yagl_gles_driver.h"
6 #include "yagl_gles_validate.h"
7
8 static void yagl_gles_framebuffer_destroy(struct yagl_ref *ref)
9 {
10     struct yagl_gles_framebuffer *fb = (struct yagl_gles_framebuffer*)ref;
11
12     if (!fb->base.nodelete) {
13         fb->driver_ps->DeleteFramebuffers(fb->driver_ps, 1, &fb->global_name);
14     }
15
16     qemu_mutex_destroy(&fb->mutex);
17
18     yagl_object_cleanup(&fb->base);
19
20     g_free(fb);
21 }
22
23 struct yagl_gles_framebuffer
24     *yagl_gles_framebuffer_create(struct yagl_gles_driver_ps *driver_ps)
25 {
26     GLuint global_name = 0;
27     struct yagl_gles_framebuffer *fb;
28     int i;
29
30     driver_ps->GenFramebuffers(driver_ps, 1, &global_name);
31
32     fb = g_malloc0(sizeof(*fb));
33
34     yagl_object_init(&fb->base, &yagl_gles_framebuffer_destroy);
35
36     fb->driver_ps = driver_ps;
37     fb->global_name = global_name;
38
39     qemu_mutex_init(&fb->mutex);
40
41     for (i = 0; i < YAGL_NUM_GLES_FRAMEBUFFER_ATTACHMENTS; ++i) {
42         fb->attachment_states[i].type = GL_NONE;
43     }
44
45     return fb;
46 }
47
48 void yagl_gles_framebuffer_acquire(struct yagl_gles_framebuffer *fb)
49 {
50     if (fb) {
51         yagl_object_acquire(&fb->base);
52     }
53 }
54
55 void yagl_gles_framebuffer_release(struct yagl_gles_framebuffer *fb)
56 {
57     if (fb) {
58         yagl_object_release(&fb->base);
59     }
60 }
61
62 bool yagl_gles_framebuffer_renderbuffer(struct yagl_gles_framebuffer *fb,
63                                         GLenum target,
64                                         GLenum attachment,
65                                         GLenum renderbuffer_target,
66                                         struct yagl_gles_renderbuffer *rb,
67                                         yagl_object_name rb_local_name)
68 {
69     yagl_gles_framebuffer_attachment framebuffer_attachment;
70
71     if (!yagl_gles_validate_framebuffer_attachment(attachment,
72                                                    &framebuffer_attachment)) {
73         return false;
74     }
75
76     if (rb && (renderbuffer_target != GL_RENDERBUFFER)) {
77         return false;
78     }
79
80     qemu_mutex_lock(&fb->mutex);
81
82     if (rb) {
83         fb->attachment_states[framebuffer_attachment].type = GL_RENDERBUFFER;
84         fb->attachment_states[framebuffer_attachment].local_name = rb_local_name;
85     } else {
86         fb->attachment_states[framebuffer_attachment].type = GL_NONE;
87         fb->attachment_states[framebuffer_attachment].local_name = 0;
88     }
89
90     /*
91      * Standalone stencil attachments are not supported on modern
92      * desktop graphics cards, so we just drop it here. Currently this
93      * doesn't do us any harm, but apps in target system that use
94      * framebuffers with stencil buffers might not be displayed correctly.
95      * If this ever happens we'll have to work around here by create some
96      * dummy texture with both color and stencil buffers and copying stencil
97      * data from that texture to texture/renderbuffer being attached here.
98      */
99     if (attachment != GL_STENCIL_ATTACHMENT) {
100         fb->driver_ps->FramebufferRenderbuffer(fb->driver_ps,
101                                                target,
102                                                attachment,
103                                                renderbuffer_target,
104                                                (rb ? rb->global_name : 0));
105     }
106
107     qemu_mutex_unlock(&fb->mutex);
108
109     return true;
110 }
111
112 bool yagl_gles_framebuffer_texture2d(struct yagl_gles_framebuffer *fb,
113                                      GLenum target,
114                                      GLenum attachment,
115                                      GLenum textarget,
116                                      GLint level,
117                                      struct yagl_gles_texture *texture,
118                                      yagl_object_name texture_local_name)
119 {
120     yagl_gles_framebuffer_attachment framebuffer_attachment;
121     GLenum squashed_textarget;
122
123     if (!yagl_gles_validate_framebuffer_attachment(attachment,
124                                                    &framebuffer_attachment)) {
125         return false;
126     }
127
128     if (texture && (level != 0)) {
129         return false;
130     }
131
132     if (!yagl_gles_validate_texture_target_squash(textarget,
133                                                   &squashed_textarget)) {
134         return false;
135     }
136
137     if (texture && (yagl_gles_texture_get_target(texture) != squashed_textarget)) {
138         return false;
139     }
140
141     qemu_mutex_lock(&fb->mutex);
142
143     if (texture) {
144         fb->attachment_states[framebuffer_attachment].type = GL_TEXTURE;
145         fb->attachment_states[framebuffer_attachment].local_name = texture_local_name;
146     } else {
147         fb->attachment_states[framebuffer_attachment].type = GL_NONE;
148         fb->attachment_states[framebuffer_attachment].local_name = 0;
149     }
150
151     if (attachment != GL_STENCIL_ATTACHMENT) {
152         fb->driver_ps->FramebufferTexture2D(fb->driver_ps,
153                                             target,
154                                             attachment,
155                                             textarget,
156                                             (texture ? texture->global_name : 0),
157                                             level);
158     }
159
160     qemu_mutex_unlock(&fb->mutex);
161
162     return true;
163 }
164
165 bool yagl_gles_framebuffer_get_attachment_parameter(struct yagl_gles_framebuffer *fb,
166                                                     GLenum attachment,
167                                                     GLenum pname,
168                                                     GLint *value)
169 {
170     yagl_gles_framebuffer_attachment framebuffer_attachment;
171
172     if (!yagl_gles_validate_framebuffer_attachment(attachment,
173                                                    &framebuffer_attachment)) {
174         return false;
175     }
176
177     qemu_mutex_lock(&fb->mutex);
178
179     switch (pname) {
180     case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
181         *value = fb->attachment_states[framebuffer_attachment].type;
182         break;
183     case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
184         *value = fb->attachment_states[framebuffer_attachment].local_name;
185         break;
186     case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
187     case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
188         fb->driver_ps->GetFramebufferAttachmentParameteriv(fb->driver_ps,
189                                                            fb->global_name,
190                                                            attachment,
191                                                            pname,
192                                                            value);
193         break;
194     default:
195         qemu_mutex_unlock(&fb->mutex);
196         return false;
197     }
198
199     qemu_mutex_unlock(&fb->mutex);
200
201     return true;
202 }
203
204 void yagl_gles_framebuffer_set_bound(struct yagl_gles_framebuffer *fb)
205 {
206     qemu_mutex_lock(&fb->mutex);
207
208     fb->was_bound = true;
209
210     qemu_mutex_unlock(&fb->mutex);
211 }
212
213 bool yagl_gles_framebuffer_was_bound(struct yagl_gles_framebuffer *fb)
214 {
215     bool ret = false;
216
217     qemu_mutex_lock(&fb->mutex);
218
219     ret = fb->was_bound;
220
221     qemu_mutex_unlock(&fb->mutex);
222
223     return ret;
224 }