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 *
egl_g3d_st_manager(struct st_manager * smapi)47 egl_g3d_st_manager(struct st_manager *smapi)
48 {
49 return (struct egl_g3d_st_manager *) smapi;
50 }
51
52 static boolean
egl_g3d_st_manager_get_egl_image(struct st_manager * smapi,void * egl_image,struct st_egl_image * out)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->level = gimg->level;
76 out->layer = gimg->layer;
77
78 _eglUnlockMutex(&gsmapi->display->Mutex);
79
80 return TRUE;
81 }
82
83 static int
egl_g3d_st_manager_get_param(struct st_manager * smapi,enum st_manager_param param)84 egl_g3d_st_manager_get_param(struct st_manager *smapi,
85 enum st_manager_param param)
86 {
87 return 0;
88 }
89
90 struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay * dpy)91 egl_g3d_create_st_manager(_EGLDisplay *dpy)
92 {
93 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
94 struct egl_g3d_st_manager *gsmapi;
95
96 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
97 if (gsmapi) {
98 gsmapi->display = dpy;
99
100 gsmapi->base.screen = gdpy->native->screen;
101 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
102 gsmapi->base.get_param = egl_g3d_st_manager_get_param;
103 }
104
105 return &gsmapi->base;;
106 }
107
108 void
egl_g3d_destroy_st_manager(struct st_manager * smapi)109 egl_g3d_destroy_st_manager(struct st_manager *smapi)
110 {
111 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
112 FREE(gsmapi);
113 }
114
115 static boolean
egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface * stfbi,enum st_attachment_type statt)116 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
117 enum st_attachment_type statt)
118 {
119 return TRUE;
120 }
121
122 static void
pbuffer_reference_openvg_image(struct egl_g3d_surface * gsurf)123 pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
124 {
125 /* TODO */
126 }
127
128 static void
pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface * gsurf)129 pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface *gsurf)
130 {
131 struct egl_g3d_display *gdpy =
132 egl_g3d_display(gsurf->base.Resource.Display);
133 struct pipe_screen *screen = gdpy->native->screen;
134 struct pipe_resource templ, *ptex;
135
136 memset(&templ, 0, sizeof(templ));
137 templ.target = PIPE_TEXTURE_2D;
138 templ.last_level = 0;
139 templ.width0 = gsurf->base.Width;
140 templ.height0 = gsurf->base.Height;
141 templ.depth0 = 1;
142 templ.array_size = 1;
143 templ.format = gsurf->stvis.color_format;
144 /* for rendering and binding to texture */
145 templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
146
147 ptex = screen->resource_create(screen, &templ);
148 gsurf->render_texture = ptex;
149 }
150
151 static boolean
egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface * stfbi,const enum st_attachment_type * statts,unsigned count,struct pipe_resource ** out)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 unsigned i;
160
161 for (i = 0; i < count; i++) {
162 out[i] = NULL;
163
164 if (gsurf->stvis.render_buffer != statts[i])
165 continue;
166
167 if (!gsurf->render_texture) {
168 switch (gsurf->client_buffer_type) {
169 case EGL_NONE:
170 pbuffer_allocate_pbuffer_texture(gsurf);
171 break;
172 case EGL_OPENVG_IMAGE:
173 pbuffer_reference_openvg_image(gsurf);
174 break;
175 default:
176 break;
177 }
178
179 if (!gsurf->render_texture)
180 return FALSE;
181 }
182
183 pipe_resource_reference(&out[i], gsurf->render_texture);
184 }
185
186 return TRUE;
187 }
188
189 static boolean
egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface * stfbi,enum st_attachment_type statt)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 struct native_present_control ctrl;
196
197 memset(&ctrl, 0, sizeof(ctrl));
198 ctrl.natt = NATIVE_ATTACHMENT_FRONT_LEFT;
199
200 return gsurf->native->present(gsurf->native, &ctrl);
201 }
202
203 static boolean
egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface * stfbi,const enum st_attachment_type * statts,unsigned count,struct pipe_resource ** out)204 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
205 const enum st_attachment_type *statts,
206 unsigned count,
207 struct pipe_resource **out)
208 {
209 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
210 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
211 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
212 uint attachment_mask = 0;
213 unsigned i;
214
215 for (i = 0; i < count; i++) {
216 int natt;
217
218 switch (statts[i]) {
219 case ST_ATTACHMENT_FRONT_LEFT:
220 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
221 break;
222 case ST_ATTACHMENT_BACK_LEFT:
223 natt = NATIVE_ATTACHMENT_BACK_LEFT;
224 break;
225 case ST_ATTACHMENT_FRONT_RIGHT:
226 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
227 break;
228 case ST_ATTACHMENT_BACK_RIGHT:
229 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
230 break;
231 default:
232 natt = -1;
233 break;
234 }
235
236 if (natt >= 0)
237 attachment_mask |= 1 << natt;
238 }
239
240 if (!gsurf->native->validate(gsurf->native, attachment_mask,
241 &gsurf->sequence_number, textures, &gsurf->base.Width,
242 &gsurf->base.Height))
243 return FALSE;
244
245 for (i = 0; i < count; i++) {
246 struct pipe_resource *tex;
247 int natt;
248
249 switch (statts[i]) {
250 case ST_ATTACHMENT_FRONT_LEFT:
251 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
252 break;
253 case ST_ATTACHMENT_BACK_LEFT:
254 natt = NATIVE_ATTACHMENT_BACK_LEFT;
255 break;
256 case ST_ATTACHMENT_FRONT_RIGHT:
257 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
258 break;
259 case ST_ATTACHMENT_BACK_RIGHT:
260 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
261 break;
262 default:
263 natt = -1;
264 break;
265 }
266
267 if (natt >= 0) {
268 tex = textures[natt];
269
270 if (statts[i] == stfbi->visual->render_buffer)
271 pipe_resource_reference(&gsurf->render_texture, tex);
272
273 if (attachment_mask & (1 << natt)) {
274 /* transfer the ownership to the caller */
275 out[i] = tex;
276 attachment_mask &= ~(1 << natt);
277 }
278 else {
279 /* the attachment is listed more than once */
280 pipe_resource_reference(&out[i], tex);
281 }
282 }
283 }
284
285 return TRUE;
286 }
287
288 struct st_framebuffer_iface *
egl_g3d_create_st_framebuffer(_EGLSurface * surf)289 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
290 {
291 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
292 struct st_framebuffer_iface *stfbi;
293
294 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
295 if (!stfbi)
296 return NULL;
297
298 stfbi->visual = &gsurf->stvis;
299 p_atomic_set(&stfbi->stamp, 1);
300
301 if (gsurf->base.Type != EGL_PBUFFER_BIT) {
302 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
303 stfbi->validate = egl_g3d_st_framebuffer_validate;
304 }
305 else {
306 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
307 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
308 }
309 stfbi->st_manager_private = (void *) &gsurf->base;
310
311 return stfbi;
312 }
313
314 void
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface * stfbi)315 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
316 {
317 FREE(stfbi);
318 }
319