Merge commit 'origin/7.8'
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d_st.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
4 *
5 * Copyright (C) 2010 LunarG Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Chia-I Wu <olv@lunarg.com>
27 */
28
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_dl.h"
32 #include "eglimage.h"
33 #include "eglmutex.h"
34
35 #include "egl_g3d.h"
36 #include "egl_g3d_st.h"
37
38 struct egl_g3d_st_manager {
39 struct st_manager base;
40 _EGLDisplay *display;
41 };
42
43 static INLINE struct egl_g3d_st_manager *
44 egl_g3d_st_manager(struct st_manager *smapi)
45 {
46 return (struct egl_g3d_st_manager *) smapi;
47 }
48
49 struct st_api *
50 egl_g3d_create_st_api(enum st_api_type api)
51 {
52 const char *stmod_name;
53 struct util_dl_library *lib;
54 const struct st_module *mod;
55
56 switch (api) {
57 case ST_API_OPENGL:
58 stmod_name = ST_MODULE_OPENGL_SYMBOL;
59 break;
60 case ST_API_OPENGL_ES1:
61 stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL;
62 break;
63 case ST_API_OPENGL_ES2:
64 stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL;
65 break;
66 case ST_API_OPENVG:
67 stmod_name = ST_MODULE_OPENVG_SYMBOL;
68 break;
69 default:
70 stmod_name = NULL;
71 break;
72 }
73 if (!stmod_name)
74 return NULL;
75
76 mod = NULL;
77 lib = util_dl_open(NULL);
78 if (lib) {
79 mod = (const struct st_module *)
80 util_dl_get_proc_address(lib, stmod_name);
81 util_dl_close(lib);
82 }
83 if (!mod || mod->api != api)
84 return NULL;
85
86 return mod->create_api();
87 }
88
89 static boolean
90 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
91 struct st_egl_image *stimg)
92 {
93 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
94 EGLImageKHR handle = (EGLImageKHR) stimg->egl_image;
95 _EGLImage *img;
96 struct egl_g3d_image *gimg;
97
98 /* this is called from state trackers */
99 _eglLockMutex(&gsmapi->display->Mutex);
100
101 img = _eglLookupImage(handle, gsmapi->display);
102 if (!img) {
103 _eglUnlockMutex(&gsmapi->display->Mutex);
104 return FALSE;
105 }
106
107 gimg = egl_g3d_image(img);
108
109 stimg->texture = NULL;
110 pipe_resource_reference(&stimg->texture, gimg->texture);
111 stimg->face = gimg->face;
112 stimg->level = gimg->level;
113 stimg->zslice = gimg->zslice;
114
115 _eglUnlockMutex(&gsmapi->display->Mutex);
116
117 return TRUE;
118 }
119
120 struct st_manager *
121 egl_g3d_create_st_manager(_EGLDisplay *dpy)
122 {
123 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
124 struct egl_g3d_st_manager *gsmapi;
125
126 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
127 if (gsmapi) {
128 gsmapi->display = dpy;
129
130 gsmapi->base.screen = gdpy->native->screen;
131 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
132 }
133
134 return &gsmapi->base;;
135 }
136
137 void
138 egl_g3d_destroy_st_manager(struct st_manager *smapi)
139 {
140 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
141 FREE(gsmapi);
142 }
143
144 static boolean
145 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
146 enum st_attachment_type statt)
147 {
148 return TRUE;
149 }
150
151 static boolean
152 egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
153 const enum st_attachment_type *statts,
154 unsigned count,
155 struct pipe_resource **out)
156 {
157 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
158 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
159 struct pipe_resource templ;
160 unsigned i;
161
162 for (i = 0; i < count; i++) {
163 out[i] = NULL;
164
165 if (gsurf->stvis.render_buffer != statts[i])
166 continue;
167
168 if (!gsurf->render_texture) {
169 struct egl_g3d_display *gdpy =
170 egl_g3d_display(gsurf->base.Resource.Display);
171 struct pipe_screen *screen = gdpy->native->screen;
172
173 memset(&templ, 0, sizeof(templ));
174 templ.target = PIPE_TEXTURE_2D;
175 templ.last_level = 0;
176 templ.width0 = gsurf->base.Width;
177 templ.height0 = gsurf->base.Height;
178 templ.depth0 = 1;
179 templ.format = gsurf->stvis.color_format;
180 templ.bind = PIPE_BIND_RENDER_TARGET;
181
182 gsurf->render_texture = screen->resource_create(screen, &templ);
183 }
184
185 pipe_resource_reference(&out[i], gsurf->render_texture);
186 }
187
188 return TRUE;
189 }
190
191 static boolean
192 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
193 enum st_attachment_type statt)
194 {
195 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
196 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
197
198 return gsurf->native->flush_frontbuffer(gsurf->native);
199 }
200
201 static boolean
202 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
203 const enum st_attachment_type *statts,
204 unsigned count,
205 struct pipe_resource **out)
206 {
207 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
208 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
209 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
210 uint attachment_mask = 0;
211 unsigned i;
212
213 for (i = 0; i < count; i++) {
214 int natt;
215
216 switch (statts[i]) {
217 case ST_ATTACHMENT_FRONT_LEFT:
218 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
219 break;
220 case ST_ATTACHMENT_BACK_LEFT:
221 natt = NATIVE_ATTACHMENT_BACK_LEFT;
222 break;
223 case ST_ATTACHMENT_FRONT_RIGHT:
224 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
225 break;
226 case ST_ATTACHMENT_BACK_RIGHT:
227 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
228 break;
229 default:
230 natt = -1;
231 break;
232 }
233
234 if (natt >= 0)
235 attachment_mask |= 1 << natt;
236 }
237
238 if (!gsurf->native->validate(gsurf->native, attachment_mask,
239 &gsurf->sequence_number, textures, &gsurf->base.Width,
240 &gsurf->base.Height))
241 return FALSE;
242
243 for (i = 0; i < count; i++) {
244 struct pipe_resource *tex;
245 int natt;
246
247 switch (statts[i]) {
248 case ST_ATTACHMENT_FRONT_LEFT:
249 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
250 break;
251 case ST_ATTACHMENT_BACK_LEFT:
252 natt = NATIVE_ATTACHMENT_BACK_LEFT;
253 break;
254 case ST_ATTACHMENT_FRONT_RIGHT:
255 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
256 break;
257 case ST_ATTACHMENT_BACK_RIGHT:
258 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
259 break;
260 default:
261 natt = -1;
262 break;
263 }
264
265 if (natt >= 0) {
266 tex = textures[natt];
267
268 if (statts[i] == stfbi->visual->render_buffer)
269 pipe_resource_reference(&gsurf->render_texture, tex);
270
271 if (attachment_mask & (1 << natt)) {
272 /* transfer the ownership to the caller */
273 out[i] = tex;
274 attachment_mask &= ~(1 << natt);
275 }
276 else {
277 /* the attachment is listed more than once */
278 pipe_resource_reference(&out[i], tex);
279 }
280 }
281 }
282
283 return TRUE;
284 }
285
286 struct st_framebuffer_iface *
287 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
288 {
289 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
290 struct st_framebuffer_iface *stfbi;
291
292 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
293 if (!stfbi)
294 return NULL;
295
296 stfbi->visual = &gsurf->stvis;
297 if (gsurf->base.Type != EGL_PBUFFER_BIT) {
298 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
299 stfbi->validate = egl_g3d_st_framebuffer_validate;
300 }
301 else {
302 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
303 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
304 }
305 stfbi->st_manager_private = (void *) &gsurf->base;
306
307 return stfbi;
308 }
309
310 void
311 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
312 {
313 FREE(stfbi);
314 }