• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 struct egl_g3d_st_manager {
42    struct st_manager base;
43    _EGLDisplay *display;
44 };
45 
46 static INLINE struct egl_g3d_st_manager *
egl_g3d_st_manager(struct st_manager * smapi)47 egl_g3d_st_manager(struct st_manager *smapi)
48 {
49    return (struct egl_g3d_st_manager *) smapi;
50 }
51 
52 static boolean
egl_g3d_st_manager_get_egl_image(struct st_manager * smapi,void * egl_image,struct st_egl_image * out)53 egl_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 
83 static int
egl_g3d_st_manager_get_param(struct st_manager * smapi,enum st_manager_param param)84 egl_g3d_st_manager_get_param(struct st_manager *smapi,
85                              enum st_manager_param param)
86 {
87    return 0;
88 }
89 
90 struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay * dpy)91 egl_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 
108 void
egl_g3d_destroy_st_manager(struct st_manager * smapi)109 egl_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 
115 static boolean
egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface * stfbi,enum st_attachment_type statt)116 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
117                                            enum st_attachment_type statt)
118 {
119    return TRUE;
120 }
121 
122 static void
pbuffer_reference_openvg_image(struct egl_g3d_surface * gsurf)123 pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
124 {
125    /* TODO */
126 }
127 
128 static void
pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface * gsurf)129 pbuffer_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 
151 static boolean
egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface * stfbi,const enum st_attachment_type * statts,unsigned count,struct pipe_resource ** out)152 egl_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 
189 static boolean
egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface * stfbi,enum st_attachment_type statt)190 egl_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 
203 static boolean
egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface * stfbi,const enum st_attachment_type * statts,unsigned count,struct pipe_resource ** out)204 egl_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 
288 struct st_framebuffer_iface *
egl_g3d_create_st_framebuffer(_EGLSurface * surf)289 egl_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 
314 void
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface * stfbi)315 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
316 {
317    FREE(stfbi);
318 }
319