Merge branch '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 struct util_dl_library *lib;
53 const char *proc_name;
54 struct st_api * (*proc)(void) = NULL;
55
56 switch (api) {
57 case ST_API_OPENGL:
58 proc_name = ST_CREATE_OPENGL_SYMBOL;
59 break;
60 case ST_API_OPENGL_ES1:
61 proc_name = ST_CREATE_OPENGL_ES1_SYMBOL;
62 break;
63 case ST_API_OPENGL_ES2:
64 proc_name = ST_CREATE_OPENGL_ES2_SYMBOL;
65 break;
66 case ST_API_OPENVG:
67 proc_name = ST_CREATE_OPENVG_SYMBOL;
68 break;
69 default:
70 assert(!"Unknown API Type\n");
71 return NULL;
72 }
73
74 lib = util_dl_open(NULL);
75 if (lib) {
76 proc = util_dl_get_proc_address(lib, proc_name);
77 debug_printf("%s: %s %p\n", __func__, proc_name, proc);
78 util_dl_close(lib);
79 }
80
81 if (!proc)
82 return NULL;
83
84 return proc();
85 }
86
87 static boolean
88 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
89 struct st_egl_image *stimg)
90 {
91 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
92 EGLImageKHR handle = (EGLImageKHR) stimg->egl_image;
93 _EGLImage *img;
94 struct egl_g3d_image *gimg;
95
96 /* this is called from state trackers */
97 _eglLockMutex(&gsmapi->display->Mutex);
98
99 img = _eglLookupImage(handle, gsmapi->display);
100 if (!img) {
101 _eglUnlockMutex(&gsmapi->display->Mutex);
102 return FALSE;
103 }
104
105 gimg = egl_g3d_image(img);
106
107 stimg->texture = NULL;
108 pipe_resource_reference(&stimg->texture, gimg->texture);
109 stimg->face = gimg->face;
110 stimg->level = gimg->level;
111 stimg->zslice = gimg->zslice;
112
113 _eglUnlockMutex(&gsmapi->display->Mutex);
114
115 return TRUE;
116 }
117
118 struct st_manager *
119 egl_g3d_create_st_manager(_EGLDisplay *dpy)
120 {
121 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
122 struct egl_g3d_st_manager *gsmapi;
123
124 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
125 if (gsmapi) {
126 gsmapi->display = dpy;
127
128 gsmapi->base.screen = gdpy->native->screen;
129 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
130 }
131
132 return &gsmapi->base;;
133 }
134
135 void
136 egl_g3d_destroy_st_manager(struct st_manager *smapi)
137 {
138 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
139 FREE(gsmapi);
140 }
141
142 static boolean
143 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
144 enum st_attachment_type statt)
145 {
146 return TRUE;
147 }
148
149 static boolean
150 egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
151 const enum st_attachment_type *statts,
152 unsigned count,
153 struct pipe_resource **out)
154 {
155 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
156 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
157 struct pipe_resource templ;
158 unsigned i;
159
160 for (i = 0; i < count; i++) {
161 out[i] = NULL;
162
163 if (gsurf->stvis.render_buffer != statts[i])
164 continue;
165
166 if (!gsurf->render_texture) {
167 struct egl_g3d_display *gdpy =
168 egl_g3d_display(gsurf->base.Resource.Display);
169 struct pipe_screen *screen = gdpy->native->screen;
170
171 memset(&templ, 0, sizeof(templ));
172 templ.target = PIPE_TEXTURE_2D;
173 templ.last_level = 0;
174 templ.width0 = gsurf->base.Width;
175 templ.height0 = gsurf->base.Height;
176 templ.depth0 = 1;
177 templ.format = gsurf->stvis.color_format;
178 templ.bind = PIPE_BIND_RENDER_TARGET;
179
180 gsurf->render_texture = screen->resource_create(screen, &templ);
181 }
182
183 pipe_resource_reference(&out[i], gsurf->render_texture);
184 }
185
186 return TRUE;
187 }
188
189 static boolean
190 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
191 enum st_attachment_type statt)
192 {
193 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
194 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
195
196 return gsurf->native->flush_frontbuffer(gsurf->native);
197 }
198
199 static boolean
200 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
201 const enum st_attachment_type *statts,
202 unsigned count,
203 struct pipe_resource **out)
204 {
205 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
206 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
207 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
208 uint attachment_mask = 0;
209 unsigned i;
210
211 for (i = 0; i < count; i++) {
212 int natt;
213
214 switch (statts[i]) {
215 case ST_ATTACHMENT_FRONT_LEFT:
216 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
217 break;
218 case ST_ATTACHMENT_BACK_LEFT:
219 natt = NATIVE_ATTACHMENT_BACK_LEFT;
220 break;
221 case ST_ATTACHMENT_FRONT_RIGHT:
222 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
223 break;
224 case ST_ATTACHMENT_BACK_RIGHT:
225 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
226 break;
227 default:
228 natt = -1;
229 break;
230 }
231
232 if (natt >= 0)
233 attachment_mask |= 1 << natt;
234 }
235
236 if (!gsurf->native->validate(gsurf->native, attachment_mask,
237 &gsurf->sequence_number, textures, &gsurf->base.Width,
238 &gsurf->base.Height))
239 return FALSE;
240
241 for (i = 0; i < count; i++) {
242 struct pipe_resource *tex;
243 int natt;
244
245 switch (statts[i]) {
246 case ST_ATTACHMENT_FRONT_LEFT:
247 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
248 break;
249 case ST_ATTACHMENT_BACK_LEFT:
250 natt = NATIVE_ATTACHMENT_BACK_LEFT;
251 break;
252 case ST_ATTACHMENT_FRONT_RIGHT:
253 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
254 break;
255 case ST_ATTACHMENT_BACK_RIGHT:
256 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
257 break;
258 default:
259 natt = -1;
260 break;
261 }
262
263 if (natt >= 0) {
264 tex = textures[natt];
265
266 if (statts[i] == stfbi->visual->render_buffer)
267 pipe_resource_reference(&gsurf->render_texture, tex);
268
269 if (attachment_mask & (1 << natt)) {
270 /* transfer the ownership to the caller */
271 out[i] = tex;
272 attachment_mask &= ~(1 << natt);
273 }
274 else {
275 /* the attachment is listed more than once */
276 pipe_resource_reference(&out[i], tex);
277 }
278 }
279 }
280
281 return TRUE;
282 }
283
284 struct st_framebuffer_iface *
285 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
286 {
287 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
288 struct st_framebuffer_iface *stfbi;
289
290 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
291 if (!stfbi)
292 return NULL;
293
294 stfbi->visual = &gsurf->stvis;
295 if (gsurf->base.Type != EGL_PBUFFER_BIT) {
296 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
297 stfbi->validate = egl_g3d_st_framebuffer_validate;
298 }
299 else {
300 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
301 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
302 }
303 stfbi->st_manager_private = (void *) &gsurf->base;
304
305 return stfbi;
306 }
307
308 void
309 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
310 {
311 FREE(stfbi);
312 }