egl_g3d_st.c revision f69b35fa15f43747dde29addaeec845604d7e127
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
37struct egl_g3d_st_manager {
38   struct st_manager base;
39   _EGLDisplay *display;
40};
41
42static INLINE struct egl_g3d_st_manager *
43egl_g3d_st_manager(struct st_manager *smapi)
44{
45   return (struct egl_g3d_st_manager *) smapi;
46}
47
48struct st_api *
49egl_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
88static boolean
89egl_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
119struct st_manager *
120egl_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
136void
137egl_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
143static boolean
144egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
145                                           enum st_attachment_type statt)
146{
147   return TRUE;
148}
149
150static boolean
151egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
152                                        const enum st_attachment_type *statts,
153                                        unsigned count,
154                                        struct pipe_texture **out)
155{
156   _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
157   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
158   struct pipe_texture templ;
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         struct egl_g3d_display *gdpy =
169            egl_g3d_display(gsurf->base.Resource.Display);
170         struct pipe_screen *screen = gdpy->native->screen;
171
172         memset(&templ, 0, sizeof(templ));
173         templ.target = PIPE_TEXTURE_2D;
174         templ.last_level = 0;
175         templ.width0 = gsurf->base.Width;
176         templ.height0 = gsurf->base.Height;
177         templ.depth0 = 1;
178         templ.format = gsurf->stvis.color_format;
179         templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
180
181         gsurf->render_texture = screen->texture_create(screen, &templ);
182      }
183
184      pipe_texture_reference(&out[i], gsurf->render_texture);
185   }
186
187   return TRUE;
188}
189
190static boolean
191egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
192                                   enum st_attachment_type statt)
193{
194   _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
195   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
196
197   return gsurf->native->flush_frontbuffer(gsurf->native);
198}
199
200static boolean
201egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
202                                const enum st_attachment_type *statts,
203                                unsigned count,
204                                struct pipe_texture **out)
205{
206   _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
207   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
208   struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
209   uint attachment_mask = 0;
210   unsigned i;
211
212   for (i = 0; i < count; i++) {
213      int natt;
214
215      switch (statts[i]) {
216      case ST_ATTACHMENT_FRONT_LEFT:
217         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
218         break;
219      case ST_ATTACHMENT_BACK_LEFT:
220         natt = NATIVE_ATTACHMENT_BACK_LEFT;
221         break;
222      case ST_ATTACHMENT_FRONT_RIGHT:
223         natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
224         break;
225      case ST_ATTACHMENT_BACK_RIGHT:
226         natt = NATIVE_ATTACHMENT_BACK_RIGHT;
227         break;
228      default:
229         natt = -1;
230         break;
231      }
232
233      if (natt >= 0)
234         attachment_mask |= 1 << natt;
235   }
236
237   if (!gsurf->native->validate(gsurf->native, attachment_mask,
238         &gsurf->sequence_number, textures, &gsurf->base.Width,
239         &gsurf->base.Height))
240      return FALSE;
241
242   for (i = 0; i < count; i++) {
243      struct pipe_texture *tex;
244      int natt;
245
246      switch (statts[i]) {
247      case ST_ATTACHMENT_FRONT_LEFT:
248         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
249         break;
250      case ST_ATTACHMENT_BACK_LEFT:
251         natt = NATIVE_ATTACHMENT_BACK_LEFT;
252         break;
253      case ST_ATTACHMENT_FRONT_RIGHT:
254         natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
255         break;
256      case ST_ATTACHMENT_BACK_RIGHT:
257         natt = NATIVE_ATTACHMENT_BACK_RIGHT;
258         break;
259      default:
260         natt = -1;
261         break;
262      }
263
264      if (natt >= 0) {
265         tex = textures[natt];
266
267         if (statts[i] == stfbi->visual->render_buffer)
268            pipe_texture_reference(&gsurf->render_texture, tex);
269
270         if (attachment_mask & (1 << natt)) {
271            /* transfer the ownership to the caller */
272            out[i] = tex;
273            attachment_mask &= ~(1 << natt);
274         }
275         else {
276            /* the attachment is listed more than once */
277            pipe_texture_reference(&out[i], tex);
278         }
279      }
280   }
281
282   return TRUE;
283}
284
285struct st_framebuffer_iface *
286egl_g3d_create_st_framebuffer(_EGLSurface *surf)
287{
288   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
289   struct st_framebuffer_iface *stfbi;
290
291   stfbi = CALLOC_STRUCT(st_framebuffer_iface);
292   if (!stfbi)
293      return NULL;
294
295   stfbi->visual = &gsurf->stvis;
296   if (gsurf->base.Type != EGL_PBUFFER_BIT) {
297      stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
298      stfbi->validate = egl_g3d_st_framebuffer_validate;
299   }
300   else {
301      stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
302      stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
303   }
304   stfbi->st_manager_private = (void *) &gsurf->base;
305
306   return stfbi;
307}
308
309void
310egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
311{
312   free(stfbi);
313}
314