egl_g3d_st.c revision 0ae4b23c534bc4182a019ab7d6a174588a42f844
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
41struct egl_g3d_st_manager {
42   struct st_manager base;
43   _EGLDisplay *display;
44};
45
46static INLINE struct egl_g3d_st_manager *
47egl_g3d_st_manager(struct st_manager *smapi)
48{
49   return (struct egl_g3d_st_manager *) smapi;
50}
51
52static boolean
53egl_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
84static int
85egl_g3d_st_manager_get_param(struct st_manager *smapi,
86                             enum st_manager_param param)
87{
88   return 0;
89}
90
91struct st_manager *
92egl_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
109void
110egl_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
116static boolean
117egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
118                                           enum st_attachment_type statt)
119{
120   return TRUE;
121}
122
123static void
124pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
125{
126   /* TODO */
127}
128
129static void
130pbuffer_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
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_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
188static boolean
189egl_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
199static boolean
200egl_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
284struct st_framebuffer_iface *
285egl_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
308void
309egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
310{
311   FREE(stfbi);
312}
313