6e5ea960e3dbead323ba9791cc8e1d08fe78918b
[profile/ivi/mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d_st.c
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
38 struct egl_g3d_st_manager {
39    struct st_manager base;
40    _EGLDisplay *display;
41 };
42
43 static INLINE struct egl_g3d_st_manager *
44 egl_g3d_st_manager(struct st_manager *smapi)
45 {
46    return (struct egl_g3d_st_manager *) smapi;
47 }
48
49 struct st_api *
50 egl_g3d_create_st_api(enum st_api_type api)
51 {
52    const char *stmod_name;
53    struct util_dl_library *lib;
54    const struct st_module *mod;
55
56    switch (api) {
57    case ST_API_OPENGL:
58       stmod_name = ST_MODULE_OPENGL_SYMBOL;
59       break;
60    case ST_API_OPENGL_ES1:
61       stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL;
62       break;
63    case ST_API_OPENGL_ES2:
64       stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL;
65       break;
66    case ST_API_OPENVG:
67       stmod_name = ST_MODULE_OPENVG_SYMBOL;
68       break;
69    default:
70       stmod_name = NULL;
71       break;
72    }
73    if (!stmod_name)
74       return NULL;
75
76    mod = NULL;
77    lib = util_dl_open(NULL);
78    if (lib) {
79       mod = (const struct st_module *)
80          util_dl_get_proc_address(lib, stmod_name);
81       util_dl_close(lib);
82    }
83    if (!mod || mod->api != api)
84       return NULL;
85
86    return mod->create_api();
87 }
88
89 static boolean
90 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
91                                  struct st_egl_image *stimg)
92 {
93    struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
94    EGLImageKHR handle = (EGLImageKHR) stimg->egl_image;
95    _EGLImage *img;
96    struct egl_g3d_image *gimg;
97
98    /* this is called from state trackers */
99    _eglLockMutex(&gsmapi->display->Mutex);
100
101    img = _eglLookupImage(handle, gsmapi->display);
102    if (!img) {
103       _eglUnlockMutex(&gsmapi->display->Mutex);
104       return FALSE;
105    }
106
107    gimg = egl_g3d_image(img);
108
109    stimg->texture = NULL;
110    pipe_texture_reference(&stimg->texture, gimg->texture);
111    stimg->face = gimg->face;
112    stimg->level = gimg->level;
113    stimg->zslice = gimg->zslice;
114
115    _eglUnlockMutex(&gsmapi->display->Mutex);
116
117    return TRUE;
118 }
119
120 struct st_manager *
121 egl_g3d_create_st_manager(_EGLDisplay *dpy)
122 {
123    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
124    struct egl_g3d_st_manager *gsmapi;
125
126    gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
127    if (gsmapi) {
128       gsmapi->display = dpy;
129
130       gsmapi->base.screen = gdpy->native->screen;
131       gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
132    }
133
134    return &gsmapi->base;;
135 }
136
137 void
138 egl_g3d_destroy_st_manager(struct st_manager *smapi)
139 {
140    struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
141    free(gsmapi);
142 }
143
144 static boolean
145 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
146                                            enum st_attachment_type statt)
147 {
148    return TRUE;
149 }
150
151 static boolean 
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_texture **out)
156 {
157    _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
158    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
159    struct pipe_texture templ;
160    unsigned i;
161
162    for (i = 0; i < count; i++) {
163       out[i] = NULL;
164
165       if (gsurf->stvis.render_buffer != statts[i])
166          continue;
167
168       if (!gsurf->render_texture) {
169          struct egl_g3d_display *gdpy =
170             egl_g3d_display(gsurf->base.Resource.Display);
171          struct pipe_screen *screen = gdpy->native->screen;
172
173          memset(&templ, 0, sizeof(templ));
174          templ.target = PIPE_TEXTURE_2D;
175          templ.last_level = 0;
176          templ.width0 = gsurf->base.Width;
177          templ.height0 = gsurf->base.Height;
178          templ.depth0 = 1;
179          templ.format = gsurf->stvis.color_format;
180          templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
181
182          gsurf->render_texture = screen->texture_create(screen, &templ);
183       }
184
185       pipe_texture_reference(&out[i], gsurf->render_texture);
186    }
187
188    return TRUE;
189 }
190
191 static boolean
192 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
193                                    enum st_attachment_type statt)
194 {
195    _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
196    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
197
198    return gsurf->native->flush_frontbuffer(gsurf->native);
199 }
200
201 static boolean 
202 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
203                                 const enum st_attachment_type *statts,
204                                 unsigned count,
205                                 struct pipe_texture **out)
206 {
207    _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
208    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
209    struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
210    uint attachment_mask = 0;
211    unsigned i;
212
213    for (i = 0; i < count; i++) {
214       int natt;
215
216       switch (statts[i]) {
217       case ST_ATTACHMENT_FRONT_LEFT:
218          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
219          break;
220       case ST_ATTACHMENT_BACK_LEFT:
221          natt = NATIVE_ATTACHMENT_BACK_LEFT;
222          break;
223       case ST_ATTACHMENT_FRONT_RIGHT:
224          natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
225          break;
226       case ST_ATTACHMENT_BACK_RIGHT:
227          natt = NATIVE_ATTACHMENT_BACK_RIGHT;
228          break;
229       default:
230          natt = -1;
231          break;
232       }
233
234       if (natt >= 0)
235          attachment_mask |= 1 << natt;
236    }
237
238    if (!gsurf->native->validate(gsurf->native, attachment_mask,
239          &gsurf->sequence_number, textures, &gsurf->base.Width,
240          &gsurf->base.Height))
241       return FALSE;
242
243    for (i = 0; i < count; i++) {
244       struct pipe_texture *tex;
245       int natt;
246
247       switch (statts[i]) {
248       case ST_ATTACHMENT_FRONT_LEFT:
249          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
250          break;
251       case ST_ATTACHMENT_BACK_LEFT:
252          natt = NATIVE_ATTACHMENT_BACK_LEFT;
253          break;
254       case ST_ATTACHMENT_FRONT_RIGHT:
255          natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
256          break;
257       case ST_ATTACHMENT_BACK_RIGHT:
258          natt = NATIVE_ATTACHMENT_BACK_RIGHT;
259          break;
260       default:
261          natt = -1;
262          break;
263       }
264
265       if (natt >= 0) {
266          tex = textures[natt];
267
268          if (statts[i] == stfbi->visual->render_buffer)
269             pipe_texture_reference(&gsurf->render_texture, tex);
270
271          if (attachment_mask & (1 << natt)) {
272             /* transfer the ownership to the caller */
273             out[i] = tex;
274             attachment_mask &= ~(1 << natt);
275          }
276          else {
277             /* the attachment is listed more than once */
278             pipe_texture_reference(&out[i], tex);
279          }
280       }
281    }
282
283    return TRUE;
284 }
285
286 struct st_framebuffer_iface *
287 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
288 {
289    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
290    struct st_framebuffer_iface *stfbi;
291
292    stfbi = CALLOC_STRUCT(st_framebuffer_iface);
293    if (!stfbi)
294       return NULL;
295
296    stfbi->visual = &gsurf->stvis;
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
310 void
311 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
312 {
313    free(stfbi);
314 }