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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "util/u_memory.h"
29 #include "util/u_inlines.h"
30 #include "util/u_dl.h"
31 #include "eglimage.h"
32 #include "eglmutex.h"
33
34 #include "egl_g3d.h"
35 #include "egl_g3d_st.h"
36
37 struct egl_g3d_st_manager {
38 struct st_manager base;
39 _EGLDisplay *display;
40 };
41
42 static INLINE struct egl_g3d_st_manager *
43 egl_g3d_st_manager(struct st_manager *smapi)
44 {
45 return (struct egl_g3d_st_manager *) smapi;
46 }
47
48 struct st_api *
49 egl_g3d_create_st_api(enum st_api_type api)
50 {
51 const char *stmod_name;
52 struct util_dl_library *lib;
53 const struct st_module *mod;
54
55 switch (api) {
56 case ST_API_OPENGL:
57 stmod_name = ST_MODULE_OPENGL_SYMBOL;
58 break;
59 case ST_API_OPENGL_ES1:
60 stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL;
61 break;
62 case ST_API_OPENGL_ES2:
63 stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL;
64 break;
65 case ST_API_OPENVG:
66 stmod_name = ST_MODULE_OPENVG_SYMBOL;
67 break;
68 default:
69 stmod_name = NULL;
70 break;
71 }
72 if (!stmod_name)
73 return NULL;
74
75 mod = NULL;
76 lib = util_dl_open(NULL);
77 if (lib) {
78 mod = (const struct st_module *)
79 util_dl_get_proc_address(lib, stmod_name);
80 util_dl_close(lib);
81 }
82 if (!mod || mod->api != api)
83 return NULL;
84
85 return mod->create_api();
86 }
87
88 static boolean
89 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
90 struct st_egl_image *stimg)
91 {
92 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
93 EGLImageKHR handle = (EGLImageKHR) stimg->egl_image;
94 _EGLImage *img;
95 struct egl_g3d_image *gimg;
96
97 /* this is called from state trackers */
98 _eglLockMutex(&gsmapi->display->Mutex);
99
100 img = _eglLookupImage(handle, gsmapi->display);
101 if (!img) {
102 _eglUnlockMutex(&gsmapi->display->Mutex);
103 return FALSE;
104 }
105
106 gimg = egl_g3d_image(img);
107
108 stimg->texture = NULL;
109 pipe_texture_reference(&stimg->texture, gimg->texture);
110 stimg->face = gimg->face;
111 stimg->level = gimg->level;
112 stimg->zslice = gimg->zslice;
113
114 _eglUnlockMutex(&gsmapi->display->Mutex);
115
116 return TRUE;
117 }
118
119 struct st_manager *
120 egl_g3d_create_st_manager(_EGLDisplay *dpy)
121 {
122 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
123 struct egl_g3d_st_manager *gsmapi;
124
125 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
126 if (gsmapi) {
127 gsmapi->display = dpy;
128
129 gsmapi->base.screen = gdpy->native->screen;
130 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
131 }
132
133 return &gsmapi->base;;
134 }
135
136 void
137 egl_g3d_destroy_st_manager(struct st_manager *smapi)
138 {
139 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
140 free(gsmapi);
141 }
142
143 static boolean
144 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
145 enum st_attachment_type statt)
146 {
147 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
148 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
149
150 return gsurf->native->flush_frontbuffer(gsurf->native);
151 }
152
153 static boolean
154 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
155 const enum st_attachment_type *statts,
156 unsigned count,
157 struct pipe_texture **out)
158 {
159 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
160 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
161 struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
162 uint attachment_mask = 0;
163 unsigned i;
164
165 for (i = 0; i < count; i++) {
166 int natt;
167
168 switch (statts[i]) {
169 case ST_ATTACHMENT_FRONT_LEFT:
170 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
171 break;
172 case ST_ATTACHMENT_BACK_LEFT:
173 natt = NATIVE_ATTACHMENT_BACK_LEFT;
174 break;
175 case ST_ATTACHMENT_FRONT_RIGHT:
176 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
177 break;
178 case ST_ATTACHMENT_BACK_RIGHT:
179 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
180 break;
181 default:
182 natt = -1;
183 break;
184 }
185
186 if (natt >= 0)
187 attachment_mask |= 1 << natt;
188 }
189
190 if (!gsurf->native->validate(gsurf->native, attachment_mask,
191 &gsurf->sequence_number, textures, &gsurf->base.Width,
192 &gsurf->base.Height))
193 return FALSE;
194
195 for (i = 0; i < count; i++) {
196 struct pipe_texture *tex;
197 int natt;
198
199 switch (statts[i]) {
200 case ST_ATTACHMENT_FRONT_LEFT:
201 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
202 break;
203 case ST_ATTACHMENT_BACK_LEFT:
204 natt = NATIVE_ATTACHMENT_BACK_LEFT;
205 break;
206 case ST_ATTACHMENT_FRONT_RIGHT:
207 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
208 break;
209 case ST_ATTACHMENT_BACK_RIGHT:
210 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
211 break;
212 default:
213 natt = -1;
214 break;
215 }
216
217 if (natt >= 0) {
218 tex = textures[natt];
219
220 if (statts[i] == stfbi->visual->render_buffer)
221 pipe_texture_reference(&gsurf->render_texture, tex);
222
223 if (attachment_mask & (1 << natt)) {
224 /* transfer the ownership to the caller */
225 out[i] = tex;
226 attachment_mask &= ~(1 << natt);
227 }
228 else {
229 /* the attachment is listed more than once */
230 pipe_texture_reference(&out[i], tex);
231 }
232 }
233 }
234
235 return TRUE;
236 }
237
238 struct st_framebuffer_iface *
239 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
240 {
241 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
242 struct st_framebuffer_iface *stfbi;
243
244 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
245 if (!stfbi)
246 return NULL;
247
248 stfbi->visual = &gsurf->stvis;
249 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
250 stfbi->validate = egl_g3d_st_framebuffer_validate;
251 stfbi->st_manager_private = (void *) &gsurf->base;
252
253 return stfbi;
254 }
255
256 void
257 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
258 {
259 free(stfbi);
260 }