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