st/egl: Add helper functions for use by backends.
[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 struct pipe_surface *present_surfaces[NUM_NATIVE_ATTACHMENTS];
44 uint resource_mask;
45 uint width, height;
46 };
47
48 struct resource_surface *
49 resource_surface_create(struct pipe_screen *screen,
50 enum pipe_format format, uint bind)
51 {
52 struct resource_surface *rsurf = CALLOC_STRUCT(resource_surface);
53
54 if (rsurf) {
55 rsurf->screen = screen;
56 rsurf->format = format;
57 rsurf->bind = bind;
58 }
59
60 return rsurf;
61 }
62
63 static void
64 resource_surface_free_resources(struct resource_surface *rsurf)
65 {
66 if (rsurf->resource_mask) {
67 int i;
68
69 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
70 if (rsurf->present_surfaces[i])
71 pipe_surface_reference(&rsurf->present_surfaces[i], NULL);
72 if (rsurf->resources[i])
73 pipe_resource_reference(&rsurf->resources[i], NULL);
74 }
75 rsurf->resource_mask = 0x0;
76 }
77 }
78
79 void
80 resource_surface_destroy(struct resource_surface *rsurf)
81 {
82 resource_surface_free_resources(rsurf);
83 FREE(rsurf);
84 }
85
86 boolean
87 resource_surface_set_size(struct resource_surface *rsurf,
88 uint width, uint height)
89 {
90 boolean changed = FALSE;
91
92 if (rsurf->width != width || rsurf->height != height) {
93 resource_surface_free_resources(rsurf);
94 rsurf->width = width;
95 rsurf->height = height;
96 changed = TRUE;
97 }
98
99 return changed;
100 }
101
102 void
103 resource_surface_get_size(struct resource_surface *rsurf,
104 uint *width, uint *height)
105 {
106 if (width)
107 *width = rsurf->width;
108 if (height)
109 *height = rsurf->height;
110 }
111
112 boolean
113 resource_surface_add_resources(struct resource_surface *rsurf,
114 uint resource_mask)
115 {
116 struct pipe_resource templ;
117 int i;
118
119 resource_mask &= ~rsurf->resource_mask;
120 if (!resource_mask)
121 return TRUE;
122
123 if (!rsurf->width || !rsurf->height)
124 return FALSE;
125
126 memset(&templ, 0, sizeof(templ));
127 templ.target = PIPE_TEXTURE_2D;
128 templ.format = rsurf->format;
129 templ.bind = rsurf->bind;
130 templ.width0 = rsurf->width;
131 templ.height0 = rsurf->height;
132 templ.depth0 = 1;
133
134 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
135 if (resource_mask & (1 <<i)) {
136 assert(!rsurf->resources[i]);
137
138 rsurf->resources[i] =
139 rsurf->screen->resource_create(rsurf->screen, &templ);
140 if (rsurf->resources[i])
141 rsurf->resource_mask |= 1 << i;
142 }
143 }
144
145 return ((rsurf->resource_mask & resource_mask) == resource_mask);
146 }
147
148
149 void
150 resource_surface_get_resources(struct resource_surface *rsurf,
151 struct pipe_resource **resources,
152 uint resource_mask)
153 {
154 int i;
155
156 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
157 if (resource_mask & (1 << i)) {
158 resources[i] = NULL;
159 pipe_resource_reference(&resources[i], rsurf->resources[i]);
160 }
161 }
162 }
163
164 struct pipe_resource *
165 resource_surface_get_single_resource(struct resource_surface *rsurf,
166 enum native_attachment which)
167 {
168 struct pipe_resource *pres = NULL;
169 pipe_resource_reference(&pres, rsurf->resources[which]);
170 return pres;
171 }
172
173 static INLINE void
174 pointer_swap(const void **p1, const void **p2)
175 {
176 const void *tmp = *p1;
177 *p1 = *p2;
178 *p2 = tmp;
179 }
180
181 void
182 resource_surface_swap_buffers(struct resource_surface *rsurf,
183 enum native_attachment buf1,
184 enum native_attachment buf2,
185 boolean only_if_exist)
186 {
187 const uint buf1_bit = 1 << buf1;
188 const uint buf2_bit = 1 << buf2;
189 uint mask;
190
191 if (only_if_exist && !(rsurf->resources[buf1] && rsurf->resources[buf2]))
192 return;
193
194 pointer_swap((const void **) &rsurf->resources[buf1],
195 (const void **) &rsurf->resources[buf2]);
196 pointer_swap((const void **) &rsurf->present_surfaces[buf1],
197 (const void **) &rsurf->present_surfaces[buf2]);
198
199 /* swap mask bits */
200 mask = rsurf->resource_mask & ~(buf1_bit | buf2_bit);
201 if (rsurf->resource_mask & buf1_bit)
202 mask |= buf2_bit;
203 if (rsurf->resource_mask & buf2_bit)
204 mask |= buf1_bit;
205
206 rsurf->resource_mask = mask;
207 }
208
209 boolean
210 resource_surface_present(struct resource_surface *rsurf,
211 enum native_attachment which,
212 void *winsys_drawable_handle)
213 {
214 struct pipe_resource *pres = rsurf->resources[which];
215 struct pipe_surface *psurf = rsurf->present_surfaces[which];
216
217 if (!pres)
218 return TRUE;
219
220 if (!psurf) {
221 psurf = rsurf->screen->get_tex_surface(rsurf->screen,
222 pres, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET);
223 if (!psurf)
224 return FALSE;
225
226 rsurf->present_surfaces[which] = psurf;
227 }
228
229 assert(psurf->texture == pres);
230
231 rsurf->screen->flush_frontbuffer(rsurf->screen,
232 psurf, winsys_drawable_handle);
233
234 return TRUE;
235 }