egl_g3d_st.c revision ac8fdbc1c723afb19eeaba5457ba78d0bf33b8d4
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->level = gimg->level;
76   out->layer = gimg->layer;
77
78   _eglUnlockMutex(&gsmapi->display->Mutex);
79
80   return TRUE;
81}
82
83static int
84egl_g3d_st_manager_get_param(struct st_manager *smapi,
85                             enum st_manager_param param)
86{
87   return 0;
88}
89
90struct st_manager *
91egl_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
108void
109egl_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
115static boolean
116egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
117                                           enum st_attachment_type statt)
118{
119   return TRUE;
120}
121
122static void
123pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
124{
125   /* TODO */
126}
127
128static void
129pbuffer_allocate_render_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   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   p_atomic_set(&stfbi->stamp, 1);
296
297   if (gsurf->base.Type != EGL_PBUFFER_BIT) {
298      stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
299      stfbi->validate = egl_g3d_st_framebuffer_validate;
300   }
301   else {
302      stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
303      stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
304   }
305   stfbi->st_manager_private = (void *) &gsurf->base;
306
307   return stfbi;
308}
309
310void
311egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
312{
313   FREE(stfbi);
314}
315