Merge branch '7.8'
[mesa.git] / src / gallium / state_trackers / dri / common / dri_st_api.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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "util/u_memory.h"
29 #include "util/u_inlines.h"
30 #include "util/u_format.h"
31 #include "util/u_debug.h"
32 #include "state_tracker/st_manager.h" /* for st_manager_create_api */
33
34 #include "dri_screen.h"
35 #include "dri_context.h"
36 #include "dri_drawable.h"
37 #include "dri_st_api.h"
38 #ifndef __NOT_HAVE_DRM_H
39 #include "dri1.h"
40 #include "dri2.h"
41 #else
42 #include "drisw.h"
43 #endif
44
45 static boolean
46 dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
47 const enum st_attachment_type *statts,
48 unsigned count,
49 struct pipe_texture **out)
50 {
51 struct dri_drawable *drawable =
52 (struct dri_drawable *) stfbi->st_manager_private;
53 unsigned statt_mask, new_mask;
54 boolean new_stamp;
55 int i;
56
57 statt_mask = 0x0;
58 for (i = 0; i < count; i++)
59 statt_mask |= (1 << statts[i]);
60
61 /* record newly allocated textures */
62 new_mask = (statt_mask & ~drawable->texture_mask);
63
64 /*
65 * dPriv->pStamp is the server stamp. It should be accessed with a lock, at
66 * least for DRI1. dPriv->lastStamp is the client stamp. It has the value
67 * of the server stamp when last checked.
68 */
69 new_stamp = (drawable->texture_stamp != drawable->dPriv->lastStamp);
70
71 if (new_stamp || new_mask) {
72
73 #ifndef __NOT_HAVE_DRM_H
74 if (__dri1_api_hooks) {
75 dri1_allocate_textures(drawable, statt_mask);
76 }
77 else {
78 dri2_allocate_textures(drawable, statts, count);
79 }
80 #else
81 if (new_stamp)
82 drisw_update_drawable_info(drawable);
83
84 drisw_allocate_textures(drawable, statt_mask);
85 #endif
86
87 /* add existing textures */
88 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
89 if (drawable->textures[i])
90 statt_mask |= (1 << i);
91 }
92
93 drawable->texture_stamp = drawable->dPriv->lastStamp;
94 drawable->texture_mask = statt_mask;
95 }
96
97 if (!out)
98 return TRUE;
99
100 for (i = 0; i < count; i++) {
101 out[i] = NULL;
102 pipe_texture_reference(&out[i], drawable->textures[statts[i]]);
103 }
104
105 return TRUE;
106 }
107
108 static boolean
109 dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
110 enum st_attachment_type statt)
111 {
112 struct dri_drawable *drawable =
113 (struct dri_drawable *) stfbi->st_manager_private;
114
115 #ifndef __NOT_HAVE_DRM_H
116 if (__dri1_api_hooks) {
117 dri1_flush_frontbuffer(drawable, statt);
118 }
119 else {
120 dri2_flush_frontbuffer(drawable, statt);
121 }
122 #else
123 drisw_flush_frontbuffer(drawable, statt);
124 #endif
125
126 return TRUE;
127 }
128
129 /**
130 * Create a framebuffer from the given drawable.
131 */
132 struct st_framebuffer_iface *
133 dri_create_st_framebuffer(struct dri_drawable *drawable)
134 {
135 struct st_framebuffer_iface *stfbi;
136
137 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
138 if (stfbi) {
139 stfbi->visual = &drawable->stvis;
140 stfbi->flush_front = dri_st_framebuffer_flush_front;
141 stfbi->validate = dri_st_framebuffer_validate;
142 stfbi->st_manager_private = (void *) drawable;
143 }
144
145 return stfbi;
146 }
147
148 /**
149 * Destroy a framebuffer.
150 */
151 void
152 dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
153 {
154 struct dri_drawable *drawable =
155 (struct dri_drawable *) stfbi->st_manager_private;
156 int i;
157
158 for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
159 pipe_texture_reference(&drawable->textures[i], NULL);
160
161 FREE(stfbi);
162 }
163
164 /**
165 * Validate the texture at an attachment. Allocate the texture if it does not
166 * exist.
167 */
168 void
169 dri_st_framebuffer_validate_att(struct st_framebuffer_iface *stfbi,
170 enum st_attachment_type statt)
171 {
172 struct dri_drawable *drawable =
173 (struct dri_drawable *) stfbi->st_manager_private;
174 enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
175 unsigned i, count = 0;
176
177 /* check if buffer already exists */
178 if (drawable->texture_mask & (1 << statt))
179 return;
180
181 /* make sure DRI2 does not destroy existing buffers */
182 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
183 if (drawable->texture_mask & (1 << i)) {
184 statts[count++] = i;
185 }
186 }
187 statts[count++] = statt;
188
189 drawable->texture_stamp = drawable->dPriv->lastStamp - 1;
190
191 stfbi->validate(stfbi, statts, count, NULL);
192 }
193
194 /**
195 * Reference counted st_api.
196 */
197 static struct {
198 int32_t refcnt;
199 struct st_api *stapi;
200 } dri_st_api;
201
202 /**
203 * Add a reference to the st_api of the state tracker.
204 */
205 static void
206 _dri_get_st_api(void)
207 {
208 p_atomic_inc(&dri_st_api.refcnt);
209 if (p_atomic_read(&dri_st_api.refcnt) == 1)
210 dri_st_api.stapi = st_manager_create_api();
211 }
212
213 /**
214 * Remove a reference to the st_api of the state tracker.
215 */
216 static void
217 _dri_put_st_api(void)
218 {
219 struct st_api *stapi = dri_st_api.stapi;
220
221 if (p_atomic_dec_zero(&dri_st_api.refcnt)) {
222 stapi->destroy(dri_st_api.stapi);
223 dri_st_api.stapi = NULL;
224 }
225 }
226
227 /**
228 * Create a state tracker manager from the given screen.
229 */
230 struct st_manager *
231 dri_create_st_manager(struct dri_screen *screen)
232 {
233 struct st_manager *smapi;
234
235 smapi = CALLOC_STRUCT(st_manager);
236 if (smapi) {
237 smapi->screen = screen->pipe_screen;
238 _dri_get_st_api();
239 }
240
241 return smapi;
242 }
243
244 /**
245 * Destroy a state tracker manager.
246 */
247 void
248 dri_destroy_st_manager(struct st_manager *smapi)
249 {
250 _dri_put_st_api();
251 FREE(smapi);
252 }
253
254 /**
255 * Return the st_api of OpenGL state tracker.
256 */
257 struct st_api *
258 dri_get_st_api(void)
259 {
260 assert(dri_st_api.stapi);
261 return dri_st_api.stapi;
262 }