egl_g3d_st.c revision 08e1076fd2d3f6fb879dd2529e7d035d6a399da2
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_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
151static boolean
152egl_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
189static boolean
190egl_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
203static boolean
204egl_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
288struct st_framebuffer_iface *
289egl_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
314void
315egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
316{
317   FREE(stfbi);
318}
319