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