Merge remote branch 'origin/master' into pipe-video
[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_string.h"
31 #include "util/u_inlines.h"
32 #include "util/u_pointer.h"
33 #include "util/u_dl.h"
34 #include "egldriver.h"
35 #include "eglimage.h"
36 #include "eglmutex.h"
37
38 #include "egl_g3d.h"
39 #include "egl_g3d_st.h"
40
41 struct egl_g3d_st_manager {
42 struct st_manager base;
43 _EGLDisplay *display;
44 };
45
46 static INLINE struct egl_g3d_st_manager *
47 egl_g3d_st_manager(struct st_manager *smapi)
48 {
49 return (struct egl_g3d_st_manager *) smapi;
50 }
51
52 static boolean
53 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
54 void *egl_image,
55 struct st_egl_image *out)
56 {
57 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
58 EGLImageKHR handle = (EGLImageKHR) egl_image;
59 _EGLImage *img;
60 struct egl_g3d_image *gimg;
61
62 /* this is called from state trackers */
63 _eglLockMutex(&gsmapi->display->Mutex);
64
65 img = _eglLookupImage(handle, gsmapi->display);
66 if (!img) {
67 _eglUnlockMutex(&gsmapi->display->Mutex);
68 return FALSE;
69 }
70
71 gimg = egl_g3d_image(img);
72
73 out->texture = NULL;
74 pipe_resource_reference(&out->texture, gimg->texture);
75 out->face = gimg->face;
76 out->level = gimg->level;
77 out->zslice = gimg->zslice;
78
79 _eglUnlockMutex(&gsmapi->display->Mutex);
80
81 return TRUE;
82 }
83
84 static int
85 egl_g3d_st_manager_get_param(struct st_manager *smapi,
86 enum st_manager_param param)
87 {
88 return 0;
89 }
90
91 struct st_manager *
92 egl_g3d_create_st_manager(_EGLDisplay *dpy)
93 {
94 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
95 struct egl_g3d_st_manager *gsmapi;
96
97 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
98 if (gsmapi) {
99 gsmapi->display = dpy;
100
101 gsmapi->base.screen = gdpy->native->screen;
102 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
103 gsmapi->base.get_param = egl_g3d_st_manager_get_param;
104 }
105
106 return &gsmapi->base;;
107 }
108
109 void
110 egl_g3d_destroy_st_manager(struct st_manager *smapi)
111 {
112 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
113 FREE(gsmapi);
114 }
115
116 static boolean
117 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
118 enum st_attachment_type statt)
119 {
120 return TRUE;
121 }
122
123 static void
124 pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
125 {
126 /* TODO */
127 }
128
129 static void
130 pbuffer_allocate_render_texture(struct egl_g3d_surface *gsurf)
131 {
132 struct egl_g3d_display *gdpy =
133 egl_g3d_display(gsurf->base.Resource.Display);
134 struct pipe_screen *screen = gdpy->native->screen;
135 struct pipe_resource templ, *ptex;
136
137 memset(&templ, 0, sizeof(templ));
138 templ.target = PIPE_TEXTURE_2D;
139 templ.last_level = 0;
140 templ.width0 = gsurf->base.Width;
141 templ.height0 = gsurf->base.Height;
142 templ.depth0 = 1;
143 templ.format = gsurf->stvis.color_format;
144 templ.bind = PIPE_BIND_RENDER_TARGET;
145
146 ptex = screen->resource_create(screen, &templ);
147 gsurf->render_texture = ptex;
148 }
149
150 static boolean
151 egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
152 const enum st_attachment_type *statts,
153 unsigned count,
154 struct pipe_resource **out)
155 {
156 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
157 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
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 switch (gsurf->client_buffer_type) {
168 case EGL_NONE:
169 pbuffer_allocate_render_texture(gsurf);
170 break;
171 case EGL_OPENVG_IMAGE:
172 pbuffer_reference_openvg_image(gsurf);
173 break;
174 default:
175 break;
176 }
177
178 if (!gsurf->render_texture)
179 return FALSE;
180 }
181
182 pipe_resource_reference(&out[i], gsurf->render_texture);
183 }
184
185 return TRUE;
186 }
187
188 static boolean
189 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
190 enum st_attachment_type statt)
191 {
192 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
193 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
194
195 return gsurf->native->present(gsurf->native,
196 NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0);
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 }