Merge remote branch 'vdpau/pipe-video' into pipe-video
[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
147 void
148 resource_surface_get_resources(struct resource_surface *rsurf,
149 struct pipe_resource **resources,
150 uint resource_mask)
151 {
152 int i;
153
154 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
155 if (resource_mask & (1 << i)) {
156 resources[i] = NULL;
157 pipe_resource_reference(&resources[i], rsurf->resources[i]);
158 }
159 }
160 }
161
162 struct pipe_resource *
163 resource_surface_get_single_resource(struct resource_surface *rsurf,
164 enum native_attachment which)
165 {
166 struct pipe_resource *pres = NULL;
167 pipe_resource_reference(&pres, rsurf->resources[which]);
168 return pres;
169 }
170
171 static INLINE void
172 pointer_swap(const void **p1, const void **p2)
173 {
174 const void *tmp = *p1;
175 *p1 = *p2;
176 *p2 = tmp;
177 }
178
179 void
180 resource_surface_swap_buffers(struct resource_surface *rsurf,
181 enum native_attachment buf1,
182 enum native_attachment buf2,
183 boolean only_if_exist)
184 {
185 const uint buf1_bit = 1 << buf1;
186 const uint buf2_bit = 1 << buf2;
187 uint mask;
188
189 if (only_if_exist && !(rsurf->resources[buf1] && rsurf->resources[buf2]))
190 return;
191
192 pointer_swap((const void **) &rsurf->resources[buf1],
193 (const void **) &rsurf->resources[buf2]);
194
195 /* swap mask bits */
196 mask = rsurf->resource_mask & ~(buf1_bit | buf2_bit);
197 if (rsurf->resource_mask & buf1_bit)
198 mask |= buf2_bit;
199 if (rsurf->resource_mask & buf2_bit)
200 mask |= buf1_bit;
201
202 rsurf->resource_mask = mask;
203 }
204
205 boolean
206 resource_surface_present(struct resource_surface *rsurf,
207 enum native_attachment which,
208 void *winsys_drawable_handle)
209 {
210 struct pipe_resource *pres = rsurf->resources[which];
211
212 if (!pres)
213 return TRUE;
214
215 rsurf->screen->flush_frontbuffer(rsurf->screen,
216 pres, 0, 0, winsys_drawable_handle);
217
218 return TRUE;
219 }