0f00c4d13ef315ddca1188d3f6b45afab3082b6a
[mesa.git] / src / gallium / state_trackers / egl / common / native_helper.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_inlines.h"
30 #include "util/u_memory.h"
31 #include "pipe/p_screen.h"
32 #include "pipe/p_context.h"
33 #include "pipe/p_state.h"
34
35 #include "native_helper.h"
36
37 struct resource_surface {
38 struct pipe_screen *screen;
39 enum pipe_format format;
40 uint bind;
41
42 struct pipe_resource *resources[NUM_NATIVE_ATTACHMENTS];
43 uint resource_mask;
44 uint width, height;
45 };
46
47 struct resource_surface *
48 resource_surface_create(struct pipe_screen *screen,
49 enum pipe_format format, uint bind)
50 {
51 struct resource_surface *rsurf = CALLOC_STRUCT(resource_surface);
52
53 if (rsurf) {
54 rsurf->screen = screen;
55 rsurf->format = format;
56 rsurf->bind = bind;
57 }
58
59 return rsurf;
60 }
61
62 static void
63 resource_surface_free_resources(struct resource_surface *rsurf)
64 {
65 if (rsurf->resource_mask) {
66 int i;
67
68 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
69 if (rsurf->resources[i])
70 pipe_resource_reference(&rsurf->resources[i], NULL);
71 }
72 rsurf->resource_mask = 0x0;
73 }
74 }
75
76 void
77 resource_surface_destroy(struct resource_surface *rsurf)
78 {
79 resource_surface_free_resources(rsurf);
80 FREE(rsurf);
81 }
82
83 boolean
84 resource_surface_set_size(struct resource_surface *rsurf,
85 uint width, uint height)
86 {
87 boolean changed = FALSE;
88
89 if (rsurf->width != width || rsurf->height != height) {
90 resource_surface_free_resources(rsurf);
91 rsurf->width = width;
92 rsurf->height = height;
93 changed = TRUE;
94 }
95
96 return changed;
97 }
98
99 void
100 resource_surface_get_size(struct resource_surface *rsurf,
101 uint *width, uint *height)
102 {
103 if (width)
104 *width = rsurf->width;
105 if (height)
106 *height = rsurf->height;
107 }
108
109 boolean
110 resource_surface_add_resources(struct resource_surface *rsurf,
111 uint resource_mask)
112 {
113 struct pipe_resource templ;
114 int i;
115
116 resource_mask &= ~rsurf->resource_mask;
117 if (!resource_mask)
118 return TRUE;
119
120 if (!rsurf->width || !rsurf->height)
121 return FALSE;
122
123 memset(&templ, 0, sizeof(templ));
124 templ.target = PIPE_TEXTURE_2D;
125 templ.format = rsurf->format;
126 templ.bind = rsurf->bind;
127 templ.width0 = rsurf->width;
128 templ.height0 = rsurf->height;
129 templ.depth0 = 1;
130 templ.array_size = 1;
131
132 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
133 if (resource_mask & (1 <<i)) {
134 assert(!rsurf->resources[i]);
135
136 rsurf->resources[i] =
137 rsurf->screen->resource_create(rsurf->screen, &templ);
138 if (rsurf->resources[i])
139 rsurf->resource_mask |= 1 << i;
140 }
141 }
142
143 return ((rsurf->resource_mask & resource_mask) == resource_mask);
144 }
145
146 void
147 resource_surface_import_resource(struct resource_surface *rsurf,
148 enum native_attachment which,
149 struct pipe_resource *pres)
150 {
151 pipe_resource_reference(&rsurf->resources[which], pres);
152 rsurf->resource_mask |= 1 << which;
153 }
154
155 void
156 resource_surface_get_resources(struct resource_surface *rsurf,
157 struct pipe_resource **resources,
158 uint resource_mask)
159 {
160 int i;
161
162 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
163 if (resource_mask & (1 << i)) {
164 resources[i] = NULL;
165 pipe_resource_reference(&resources[i], rsurf->resources[i]);
166 }
167 }
168 }
169
170 struct pipe_resource *
171 resource_surface_get_single_resource(struct resource_surface *rsurf,
172 enum native_attachment which)
173 {
174 struct pipe_resource *pres = NULL;
175 pipe_resource_reference(&pres, rsurf->resources[which]);
176 return pres;
177 }
178
179 static INLINE void
180 pointer_swap(const void **p1, const void **p2)
181 {
182 const void *tmp = *p1;
183 *p1 = *p2;
184 *p2 = tmp;
185 }
186
187 void
188 resource_surface_swap_buffers(struct resource_surface *rsurf,
189 enum native_attachment buf1,
190 enum native_attachment buf2,
191 boolean only_if_exist)
192 {
193 const uint buf1_bit = 1 << buf1;
194 const uint buf2_bit = 1 << buf2;
195 uint mask;
196
197 if (only_if_exist && !(rsurf->resources[buf1] && rsurf->resources[buf2]))
198 return;
199
200 pointer_swap((const void **) &rsurf->resources[buf1],
201 (const void **) &rsurf->resources[buf2]);
202
203 /* swap mask bits */
204 mask = rsurf->resource_mask & ~(buf1_bit | buf2_bit);
205 if (rsurf->resource_mask & buf1_bit)
206 mask |= buf2_bit;
207 if (rsurf->resource_mask & buf2_bit)
208 mask |= buf1_bit;
209
210 rsurf->resource_mask = mask;
211 }
212
213 boolean
214 resource_surface_present(struct resource_surface *rsurf,
215 enum native_attachment which,
216 void *winsys_drawable_handle)
217 {
218 struct pipe_resource *pres = rsurf->resources[which];
219
220 if (!pres)
221 return TRUE;
222
223 rsurf->screen->flush_frontbuffer(rsurf->screen,
224 pres, 0, 0, winsys_drawable_handle);
225
226 return TRUE;
227 }
228
229 /**
230 * Schedule a copy swap from the back to the front buffer using the
231 * native display's copy context.
232 */
233 boolean
234 resource_surface_copy_swap(struct resource_surface *rsurf,
235 struct native_display *ndpy)
236 {
237 struct pipe_resource *ftex;
238 struct pipe_resource *btex;
239 struct pipe_context *pipe;
240 struct pipe_box src_box;
241 boolean ret = FALSE;
242
243 pipe = ndpy_get_copy_context(ndpy);
244 if (!pipe)
245 return FALSE;
246
247 ftex = resource_surface_get_single_resource(rsurf,
248 NATIVE_ATTACHMENT_FRONT_LEFT);
249 if (!ftex)
250 goto out_no_ftex;
251 btex = resource_surface_get_single_resource(rsurf,
252 NATIVE_ATTACHMENT_BACK_LEFT);
253 if (!btex)
254 goto out_no_btex;
255
256 u_box_origin_2d(ftex->width0, ftex->height0, &src_box);
257 pipe->resource_copy_region(pipe, ftex, 0, 0, 0, 0,
258 btex, 0, &src_box);
259 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
260 ret = TRUE;
261
262 out_no_ftex:
263 pipe_resource_reference(&btex, NULL);
264 out_no_btex:
265 pipe_resource_reference(&ftex, NULL);
266
267 return ret;
268 }