Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 2010 LunarG Inc. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
22 | * DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Chia-I Wu |
||
26 | */ |
||
27 | |||
28 | #include "util/u_memory.h" |
||
29 | #include "util/u_string.h" |
||
30 | #include "util/u_inlines.h" |
||
31 | #include "util/u_pointer.h" |
||
32 | #include "util/u_dl.h" |
||
33 | #include "egldriver.h" |
||
34 | #include "eglimage.h" |
||
35 | #include "eglmutex.h" |
||
36 | |||
37 | #include "egl_g3d.h" |
||
38 | #include "egl_g3d_st.h" |
||
39 | |||
40 | struct egl_g3d_st_manager { |
||
41 | struct st_manager base; |
||
42 | _EGLDisplay *display; |
||
43 | }; |
||
44 | |||
45 | static INLINE struct egl_g3d_st_manager * |
||
46 | egl_g3d_st_manager(struct st_manager *smapi) |
||
47 | { |
||
48 | return (struct egl_g3d_st_manager *) smapi; |
||
49 | } |
||
50 | |||
51 | static boolean |
||
52 | egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, |
||
53 | void *egl_image, |
||
54 | struct st_egl_image *out) |
||
55 | { |
||
56 | struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); |
||
57 | EGLImageKHR handle = (EGLImageKHR) egl_image; |
||
58 | _EGLImage *img; |
||
59 | struct egl_g3d_image *gimg; |
||
60 | |||
61 | /* this is called from state trackers */ |
||
62 | _eglLockMutex(&gsmapi->display->Mutex); |
||
63 | |||
64 | img = _eglLookupImage(handle, gsmapi->display); |
||
65 | if (!img) { |
||
66 | _eglUnlockMutex(&gsmapi->display->Mutex); |
||
67 | return FALSE; |
||
68 | } |
||
69 | |||
70 | gimg = egl_g3d_image(img); |
||
71 | |||
72 | out->texture = NULL; |
||
73 | pipe_resource_reference(&out->texture, gimg->texture); |
||
74 | out->level = gimg->level; |
||
75 | out->layer = gimg->layer; |
||
76 | |||
77 | _eglUnlockMutex(&gsmapi->display->Mutex); |
||
78 | |||
79 | return TRUE; |
||
80 | } |
||
81 | |||
82 | static int |
||
83 | egl_g3d_st_manager_get_param(struct st_manager *smapi, |
||
84 | enum st_manager_param param) |
||
85 | { |
||
86 | return 0; |
||
87 | } |
||
88 | |||
89 | struct st_manager * |
||
90 | egl_g3d_create_st_manager(_EGLDisplay *dpy) |
||
91 | { |
||
92 | struct egl_g3d_display *gdpy = egl_g3d_display(dpy); |
||
93 | struct egl_g3d_st_manager *gsmapi; |
||
94 | |||
95 | gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); |
||
96 | if (gsmapi) { |
||
97 | gsmapi->display = dpy; |
||
98 | |||
99 | gsmapi->base.screen = gdpy->native->screen; |
||
100 | gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image; |
||
101 | gsmapi->base.get_param = egl_g3d_st_manager_get_param; |
||
102 | } |
||
103 | |||
104 | return &gsmapi->base;; |
||
105 | } |
||
106 | |||
107 | void |
||
108 | egl_g3d_destroy_st_manager(struct st_manager *smapi) |
||
109 | { |
||
110 | struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); |
||
111 | FREE(gsmapi); |
||
112 | } |
||
113 | |||
114 | static boolean |
||
115 | egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_context_iface *stctx, |
||
116 | struct st_framebuffer_iface *stfbi, |
||
117 | enum st_attachment_type statt) |
||
118 | { |
||
119 | return TRUE; |
||
120 | } |
||
121 | |||
122 | static void |
||
123 | pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf) |
||
124 | { |
||
125 | /* TODO */ |
||
126 | } |
||
127 | |||
128 | static void |
||
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 |
||
152 | egl_g3d_st_framebuffer_validate_pbuffer(struct st_context_iface *stctx, |
||
153 | struct st_framebuffer_iface *stfbi, |
||
154 | const enum st_attachment_type *statts, |
||
155 | unsigned count, |
||
156 | struct pipe_resource **out) |
||
157 | { |
||
158 | _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; |
||
159 | struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); |
||
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 | switch (gsurf->client_buffer_type) { |
||
170 | case EGL_NONE: |
||
171 | pbuffer_allocate_pbuffer_texture(gsurf); |
||
172 | break; |
||
173 | case EGL_OPENVG_IMAGE: |
||
174 | pbuffer_reference_openvg_image(gsurf); |
||
175 | break; |
||
176 | default: |
||
177 | break; |
||
178 | } |
||
179 | |||
180 | if (!gsurf->render_texture) |
||
181 | return FALSE; |
||
182 | } |
||
183 | |||
184 | pipe_resource_reference(&out[i], gsurf->render_texture); |
||
185 | } |
||
186 | |||
187 | return TRUE; |
||
188 | } |
||
189 | |||
190 | static boolean |
||
191 | egl_g3d_st_framebuffer_flush_front(struct st_context_iface *stctx, |
||
192 | 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 | struct native_present_control ctrl; |
||
198 | |||
199 | memset(&ctrl, 0, sizeof(ctrl)); |
||
200 | ctrl.natt = NATIVE_ATTACHMENT_FRONT_LEFT; |
||
201 | |||
202 | return gsurf->native->present(gsurf->native, &ctrl); |
||
203 | } |
||
204 | |||
205 | static boolean |
||
206 | egl_g3d_st_framebuffer_validate(struct st_context_iface *stctx, |
||
207 | struct st_framebuffer_iface *stfbi, |
||
208 | const enum st_attachment_type *statts, |
||
209 | unsigned count, |
||
210 | struct pipe_resource **out) |
||
211 | { |
||
212 | _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; |
||
213 | struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); |
||
214 | struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; |
||
215 | uint attachment_mask = 0; |
||
216 | unsigned i; |
||
217 | |||
218 | for (i = 0; i < count; i++) { |
||
219 | int natt; |
||
220 | |||
221 | switch (statts[i]) { |
||
222 | case ST_ATTACHMENT_FRONT_LEFT: |
||
223 | natt = NATIVE_ATTACHMENT_FRONT_LEFT; |
||
224 | break; |
||
225 | case ST_ATTACHMENT_BACK_LEFT: |
||
226 | natt = NATIVE_ATTACHMENT_BACK_LEFT; |
||
227 | break; |
||
228 | case ST_ATTACHMENT_FRONT_RIGHT: |
||
229 | natt = NATIVE_ATTACHMENT_FRONT_RIGHT; |
||
230 | break; |
||
231 | case ST_ATTACHMENT_BACK_RIGHT: |
||
232 | natt = NATIVE_ATTACHMENT_BACK_RIGHT; |
||
233 | break; |
||
234 | default: |
||
235 | natt = -1; |
||
236 | break; |
||
237 | } |
||
238 | |||
239 | if (natt >= 0) |
||
240 | attachment_mask |= 1 << natt; |
||
241 | } |
||
242 | |||
243 | if (!gsurf->native->validate(gsurf->native, attachment_mask, |
||
244 | &gsurf->sequence_number, textures, &gsurf->base.Width, |
||
245 | &gsurf->base.Height)) |
||
246 | return FALSE; |
||
247 | |||
248 | for (i = 0; i < count; i++) { |
||
249 | struct pipe_resource *tex; |
||
250 | int natt; |
||
251 | |||
252 | switch (statts[i]) { |
||
253 | case ST_ATTACHMENT_FRONT_LEFT: |
||
254 | natt = NATIVE_ATTACHMENT_FRONT_LEFT; |
||
255 | break; |
||
256 | case ST_ATTACHMENT_BACK_LEFT: |
||
257 | natt = NATIVE_ATTACHMENT_BACK_LEFT; |
||
258 | break; |
||
259 | case ST_ATTACHMENT_FRONT_RIGHT: |
||
260 | natt = NATIVE_ATTACHMENT_FRONT_RIGHT; |
||
261 | break; |
||
262 | case ST_ATTACHMENT_BACK_RIGHT: |
||
263 | natt = NATIVE_ATTACHMENT_BACK_RIGHT; |
||
264 | break; |
||
265 | default: |
||
266 | natt = -1; |
||
267 | break; |
||
268 | } |
||
269 | |||
270 | if (natt >= 0) { |
||
271 | tex = textures[natt]; |
||
272 | |||
273 | if (statts[i] == stfbi->visual->render_buffer) |
||
274 | pipe_resource_reference(&gsurf->render_texture, tex); |
||
275 | |||
276 | if (attachment_mask & (1 << natt)) { |
||
277 | /* transfer the ownership to the caller */ |
||
278 | out[i] = tex; |
||
279 | attachment_mask &= ~(1 << natt); |
||
280 | } |
||
281 | else { |
||
282 | /* the attachment is listed more than once */ |
||
283 | pipe_resource_reference(&out[i], tex); |
||
284 | } |
||
285 | } |
||
286 | } |
||
287 | |||
288 | return TRUE; |
||
289 | } |
||
290 | |||
291 | struct st_framebuffer_iface * |
||
292 | egl_g3d_create_st_framebuffer(_EGLSurface *surf) |
||
293 | { |
||
294 | struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); |
||
295 | struct st_framebuffer_iface *stfbi; |
||
296 | |||
297 | stfbi = CALLOC_STRUCT(st_framebuffer_iface); |
||
298 | if (!stfbi) |
||
299 | return NULL; |
||
300 | |||
301 | stfbi->visual = &gsurf->stvis; |
||
302 | p_atomic_set(&stfbi->stamp, 1); |
||
303 | |||
304 | if (gsurf->base.Type != EGL_PBUFFER_BIT) { |
||
305 | stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; |
||
306 | stfbi->validate = egl_g3d_st_framebuffer_validate; |
||
307 | } |
||
308 | else { |
||
309 | stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer; |
||
310 | stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer; |
||
311 | } |
||
312 | stfbi->st_manager_private = (void *) &gsurf->base; |
||
313 | |||
314 | return stfbi; |
||
315 | } |
||
316 | |||
317 | void |
||
318 | egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) |
||
319 | { |
||
320 | FREE(stfbi); |
||
321 | }><>><>>><>>> |