radeon/r200/r300: cleanup some of the renderbuffer code
[mesa.git] / src / gallium / winsys / drm / radeon / radeon_screen.c
1 /*
2 * Copyright © 2008 Jérôme Glisse
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 */
26 /*
27 * Authors:
28 * Jérôme Glisse <glisse@freedesktop.org>
29 */
30 #include <stdio.h>
31 #include "pipe/p_screen.h"
32 #include "pipe/p_defines.h"
33 #include "pipe/p_inlines.h"
34 #include "pipe/p_context.h"
35 #include "pipe/p_state.h"
36 #include "state_tracker/st_public.h"
37 #include "state_tracker/st_context.h"
38 #include "utils.h"
39 #include "xf86drm.h"
40 #include "drm.h"
41 #include "dri_util.h"
42 #include "radeon_screen.h"
43 #include "radeon_context.h"
44 #include "radeon_buffer.h"
45 #include "radeon_bo.h"
46 #include "radeon_bo_gem.h"
47 #include "radeon_drm.h"
48
49 extern const struct dri_extension radeon_card_extensions[];
50
51 static const __DRIextension *radeon_screen_extensions[] = {
52 &driReadDrawableExtension,
53 &driCopySubBufferExtension.base,
54 &driSwapControlExtension.base,
55 &driFrameTrackingExtension.base,
56 &driMediaStreamCounterExtension.base,
57 NULL
58 };
59
60 static __DRIconfig **radeon_fill_in_modes(unsigned pixel_bits,
61 unsigned depth_bits,
62 GLboolean have_back_buffer)
63 {
64 __DRIconfig **configs;
65 unsigned depth_buffer_factor;
66 unsigned back_buffer_factor;
67 unsigned num_modes;
68 GLenum fb_format;
69 GLenum fb_type;
70 uint8_t depth_bits_array[3];
71 uint8_t stencil_bits_array[3];
72 uint8_t msaa_samples_array[1];
73 /* TODO: pageflipping ? */
74 static const GLenum back_buffer_modes[] = {
75 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
76 };
77
78 stencil_bits_array[0] = 0;
79 stencil_bits_array[1] = 0;
80 if (depth_bits == 24) {
81 stencil_bits_array[2] = 8;
82 num_modes = 3;
83 }
84
85 depth_bits_array[0] = 0;
86 depth_bits_array[1] = depth_bits;
87 depth_bits_array[2] = depth_bits;
88 depth_buffer_factor = (depth_bits == 24) ? 3 : 2;
89
90 back_buffer_factor = (have_back_buffer) ? 3 : 1;
91
92 msaa_samples_array[0] = 0;
93
94 if (pixel_bits == 16) {
95 fb_format = GL_RGB;
96 fb_type = GL_UNSIGNED_SHORT_5_6_5;
97 } else {
98 fb_format = GL_BGRA;
99 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
100 }
101
102 configs = (__DRIconfig **)driCreateConfigs(fb_format,
103 fb_type,
104 depth_bits_array,
105 stencil_bits_array,
106 depth_buffer_factor,
107 back_buffer_modes,
108 back_buffer_factor,
109 msaa_samples_array,
110 1);
111 if (configs == NULL) {
112 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
113 __FILE__, __LINE__);
114 return NULL;
115 }
116 return configs;
117 }
118
119 static void radeon_screen_destroy(__DRIscreenPrivate *dri_screen)
120 {
121 struct radeon_screen *radeon_screen = (struct radeon_screen*)dri_screen->private;
122
123 radeon_bo_manager_gem_dtor(radeon_screen->bom);
124 dri_screen = NULL;
125 free(radeon_screen);
126 }
127
128 static const __DRIconfig **radeon_screen_init(__DRIscreenPrivate *dri_screen)
129 {
130 struct radeon_screen *radeon_screen;
131
132 /* Calling driInitExtensions here, with a NULL context pointer,
133 * does not actually enable the extensions. It just makes sure
134 * that all the dispatch offsets for all the extensions that
135 * *might* be enables are known. This is needed because the
136 * dispatch offsets need to be known when _mesa_context_create is
137 * called, but we can't enable the extensions until we have a
138 * context pointer.
139 *
140 * Hello chicken. Hello egg. How are you two today?
141 */
142 driInitExtensions(NULL, radeon_card_extensions, GL_FALSE);
143
144 radeon_screen = calloc(1, sizeof(struct radeon_screen));
145 if (radeon_screen == NULL) {
146 fprintf(stderr, "\nERROR! Allocating private area failed\n");
147 return NULL;
148 }
149 dri_screen->private = (void*)radeon_screen;
150 dri_screen->extensions = radeon_screen_extensions;
151 radeon_screen->dri_screen = dri_screen;
152
153 radeon_screen->bom = radeon_bo_manager_gem_ctor(dri_screen->fd);
154 if (radeon_screen->bom == NULL) {
155 radeon_screen_destroy(dri_screen);
156 return NULL;
157 }
158
159 return driConcatConfigs(radeon_fill_in_modes(16, 16, 1),
160 radeon_fill_in_modes(32, 24, 1));
161 }
162
163 static boolean radeon_buffer_create(__DRIscreenPrivate *dri_screen,
164 __DRIdrawablePrivate *dri_drawable,
165 const __GLcontextModes *visual,
166 boolean is_pixmap)
167 {
168 if (is_pixmap) {
169 /* TODO: implement ? */
170 return GL_FALSE;
171 } else {
172 enum pipe_format color_format, depth_format, stencil_format;
173 struct radeon_framebuffer *radeon_fb;
174
175 radeon_fb = calloc(1, sizeof(struct radeon_framebuffer));
176 if (radeon_fb == NULL) {
177 return GL_FALSE;
178 }
179
180 switch (visual->redBits) {
181 case 5:
182 color_format = PIPE_FORMAT_R5G6B5_UNORM;
183 break;
184 default:
185 color_format = PIPE_FORMAT_A8R8G8B8_UNORM;
186 break;
187 }
188
189 switch (visual->depthBits) {
190 case 24:
191 depth_format = PIPE_FORMAT_S8Z24_UNORM;
192 break;
193 case 16:
194 depth_format = PIPE_FORMAT_Z16_UNORM;
195 break;
196 default:
197 depth_format = PIPE_FORMAT_NONE;
198 break;
199 }
200
201 switch (visual->stencilBits) {
202 case 8:
203 /* force depth format */
204 depth_format = PIPE_FORMAT_S8Z24_UNORM;
205 stencil_format = PIPE_FORMAT_S8Z24_UNORM;
206 break;
207 default:
208 stencil_format = PIPE_FORMAT_NONE;
209 break;
210 }
211
212 radeon_fb->st_framebuffer = st_create_framebuffer(visual,
213 color_format,
214 depth_format,
215 stencil_format,
216 dri_drawable->w,
217 dri_drawable->h,
218 (void*)radeon_fb);
219 if (radeon_fb->st_framebuffer == NULL) {
220 free(radeon_fb);
221 return GL_FALSE;
222 }
223 dri_drawable->driverPrivate = (void *) radeon_fb;
224
225 radeon_fb->attachments = (1 << __DRI_BUFFER_FRONT_LEFT);
226 if (visual->doubleBufferMode) {
227 radeon_fb->attachments |= (1 << __DRI_BUFFER_BACK_LEFT);
228 }
229 if (visual->depthBits || visual->stencilBits) {
230 radeon_fb->attachments |= (1 << __DRI_BUFFER_DEPTH);
231 }
232
233 return GL_TRUE;
234 }
235 }
236
237 static void radeon_buffer_destroy(__DRIdrawablePrivate * dri_drawable)
238 {
239 struct radeon_framebuffer *radeon_fb;
240
241 radeon_fb = dri_drawable->driverPrivate;
242 assert(radeon_fb->st_framebuffer);
243 st_unreference_framebuffer(radeon_fb->st_framebuffer);
244 free(radeon_fb);
245 }
246
247 static void radeon_swap_buffers(__DRIdrawablePrivate *dri_drawable)
248 {
249 struct radeon_framebuffer *radeon_fb;
250 struct pipe_surface *back_surf = NULL;
251
252 radeon_fb = dri_drawable->driverPrivate;
253 assert(radeon_fb);
254 assert(radeon_fb->st_framebuffer);
255
256 st_get_framebuffer_surface(radeon_fb->st_framebuffer,
257 ST_SURFACE_BACK_LEFT,
258 &back_surf);
259 if (back_surf) {
260 st_notify_swapbuffers(radeon_fb->st_framebuffer);
261 /* TODO: do we want to do anythings ? */
262 st_notify_swapbuffers_complete(radeon_fb->st_framebuffer);
263 }
264 }
265
266 /**
267 * Called via glXCopySubBufferMESA() to copy a subrect of the back
268 * buffer to the front buffer/screen.
269 */
270 static void radeon_copy_sub_buffer(__DRIdrawablePrivate *dri_drawable,
271 int x, int y, int w, int h)
272 {
273 /* TODO: ... */
274 }
275
276 const struct __DriverAPIRec driDriverAPI = {
277 .InitScreen = NULL,
278 .DestroyScreen = radeon_screen_destroy,
279 .CreateContext = radeon_context_create,
280 .DestroyContext = radeon_context_destroy,
281 .CreateBuffer = radeon_buffer_create,
282 .DestroyBuffer = radeon_buffer_destroy,
283 .SwapBuffers = radeon_swap_buffers,
284 .MakeCurrent = radeon_context_bind,
285 .UnbindContext = radeon_context_unbind,
286 .CopySubBuffer = radeon_copy_sub_buffer,
287 .InitScreen2 = radeon_screen_init,
288 };