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