r300: bo and cs abstraction.
[mesa.git] / src / mesa / drivers / dri / r300 / radeon_context.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /**
31 * \file radeon_context.c
32 * Common context initialization.
33 *
34 * \author Keith Whitwell <keith@tungstengraphics.com>
35 */
36
37 #include <dlfcn.h>
38
39 #include "main/glheader.h"
40 #include "main/imports.h"
41 #include "main/context.h"
42 #include "main/state.h"
43 #include "main/matrix.h"
44 #include "main/framebuffer.h"
45
46 #include "drivers/common/driverfuncs.h"
47 #include "swrast/swrast.h"
48
49 #include "radeon_buffer.h"
50 #include "radeon_screen.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_macros.h"
53 #include "radeon_reg.h"
54
55 #include "radeon_state.h"
56 #include "r300_state.h"
57
58 #include "utils.h"
59 #include "vblank.h"
60 #include "xmlpool.h" /* for symbolic values of enum-type options */
61 #include "drirenderbuffer.h"
62
63 #define DRIVER_DATE "20060815"
64
65
66 /* Return various strings for glGetString().
67 */
68 static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
69 {
70 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
71 static char buffer[128];
72
73 switch (name) {
74 case GL_VENDOR:
75 if (IS_R300_CLASS(radeon->radeonScreen))
76 return (GLubyte *) "DRI R300 Project";
77 else
78 return (GLubyte *) "Tungsten Graphics, Inc.";
79
80 case GL_RENDERER:
81 {
82 unsigned offset;
83 GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
84 radeon->radeonScreen->AGPMode;
85 const char* chipname;
86
87 if (IS_R300_CLASS(radeon->radeonScreen))
88 chipname = "R300";
89 else
90 chipname = "R200";
91
92 offset = driGetRendererString(buffer, chipname, DRIVER_DATE,
93 agp_mode);
94
95 if (IS_R300_CLASS(radeon->radeonScreen)) {
96 sprintf(&buffer[offset], " %sTCL",
97 (radeon->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)
98 ? "" : "NO-");
99 } else {
100 sprintf(&buffer[offset], " %sTCL",
101 !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
102 ? "" : "NO-");
103 }
104
105 return (GLubyte *) buffer;
106 }
107
108 default:
109 return NULL;
110 }
111 }
112
113 /* Initialize the driver's misc functions.
114 */
115 static void radeonInitDriverFuncs(struct dd_function_table *functions)
116 {
117 functions->GetString = radeonGetString;
118 }
119
120
121 /**
122 * Create and initialize all common fields of the context,
123 * including the Mesa context itself.
124 */
125 GLboolean radeonInitContext(radeonContextPtr radeon,
126 struct dd_function_table* functions,
127 const __GLcontextModes * glVisual,
128 __DRIcontextPrivate * driContextPriv,
129 void *sharedContextPrivate)
130 {
131 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
132 radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
133 GLcontext* ctx;
134 GLcontext* shareCtx;
135 int fthrottle_mode;
136
137 /* Fill in additional standard functions. */
138 radeonInitDriverFuncs(functions);
139
140 radeon->radeonScreen = screen;
141 /* Allocate and initialize the Mesa context */
142 if (sharedContextPrivate)
143 shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
144 else
145 shareCtx = NULL;
146 radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
147 functions, (void *)radeon);
148 if (!radeon->glCtx)
149 return GL_FALSE;
150
151 ctx = radeon->glCtx;
152 driContextPriv->driverPrivate = radeon;
153
154 /* DRI fields */
155 radeon->dri.context = driContextPriv;
156 radeon->dri.screen = sPriv;
157 radeon->dri.drawable = NULL;
158 radeon->dri.readable = NULL;
159 radeon->dri.hwContext = driContextPriv->hHWContext;
160 radeon->dri.hwLock = &sPriv->pSAREA->lock;
161 radeon->dri.fd = sPriv->fd;
162 radeon->dri.drmMinor = sPriv->drm_version.minor;
163
164 radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
165 screen->sarea_priv_offset);
166
167 /* Setup IRQs */
168 fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
169 radeon->iw.irq_seq = -1;
170 radeon->irqsEmitted = 0;
171 radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
172 radeon->radeonScreen->irq);
173
174 radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
175
176 if (!radeon->do_irqs)
177 fprintf(stderr,
178 "IRQ's not enabled, falling back to %s: %d %d\n",
179 radeon->do_usleeps ? "usleeps" : "busy waits",
180 fthrottle_mode, radeon->radeonScreen->irq);
181
182 (*sPriv->systemTime->getUST) (&radeon->swap_ust);
183
184 return GL_TRUE;
185 }
186
187
188 /**
189 * Cleanup common context fields.
190 * Called by r200DestroyContext/r300DestroyContext
191 */
192 void radeonCleanupContext(radeonContextPtr radeon)
193 {
194 /* _mesa_destroy_context() might result in calls to functions that
195 * depend on the DriverCtx, so don't set it to NULL before.
196 *
197 * radeon->glCtx->DriverCtx = NULL;
198 */
199
200 /* free the Mesa context */
201 _mesa_destroy_context(radeon->glCtx);
202
203 if (radeon->state.scissor.pClipRects) {
204 FREE(radeon->state.scissor.pClipRects);
205 radeon->state.scissor.pClipRects = 0;
206 }
207 }
208
209
210 /**
211 * Swap front and back buffer.
212 */
213 void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
214 {
215 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
216 radeonContextPtr radeon;
217 GLcontext *ctx;
218
219 radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
220 ctx = radeon->glCtx;
221
222 if (ctx->Visual.doubleBufferMode) {
223 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
224 if (radeon->doPageFlip) {
225 radeonPageFlip(dPriv);
226 } else {
227 radeonCopyBuffer(dPriv, NULL);
228 }
229 }
230 } else {
231 /* XXX this shouldn't be an error but we can't handle it for now */
232 _mesa_problem(NULL, "%s: drawable has no context!",
233 __FUNCTION__);
234 }
235 }
236
237 void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
238 int x, int y, int w, int h )
239 {
240 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
241 radeonContextPtr radeon;
242 GLcontext *ctx;
243
244 radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
245 ctx = radeon->glCtx;
246
247 if (ctx->Visual.doubleBufferMode) {
248 drm_clip_rect_t rect;
249 rect.x1 = x + dPriv->x;
250 rect.y1 = (dPriv->h - y - h) + dPriv->y;
251 rect.x2 = rect.x1 + w;
252 rect.y2 = rect.y1 + h;
253 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
254 radeonCopyBuffer(dPriv, &rect);
255 }
256 } else {
257 /* XXX this shouldn't be an error but we can't handle it for now */
258 _mesa_problem(NULL, "%s: drawable has no context!",
259 __FUNCTION__);
260 }
261 }
262
263 static void
264 radeon_make_renderbuffer_current(radeonContextPtr radeon,
265 GLframebuffer *draw)
266 {
267 int size = 4096*4096*4;
268 /* if radeon->fake */
269 struct radeon_renderbuffer *rb;
270
271 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
272
273 if (!rb->bo) {
274 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
275 radeon->radeonScreen->frontOffset +
276 radeon->radeonScreen->fbLocation,
277 size,
278 4096,
279 0);
280 }
281 rb->cpp = radeon->radeonScreen->cpp;
282 rb->pitch = radeon->radeonScreen->frontPitch;
283 }
284 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
285 if (!rb->bo) {
286 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
287 radeon->radeonScreen->backOffset +
288 radeon->radeonScreen->fbLocation,
289 size,
290 4096,
291 0);
292 }
293 rb->cpp = radeon->radeonScreen->cpp;
294 rb->pitch = radeon->radeonScreen->backPitch;
295 }
296 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
297 if (!rb->bo) {
298 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
299 radeon->radeonScreen->depthOffset +
300 radeon->radeonScreen->fbLocation,
301 size,
302 4096,
303 0);
304 }
305 rb->cpp = radeon->radeonScreen->cpp;
306 rb->pitch = radeon->radeonScreen->depthPitch;
307 }
308 }
309
310
311 /* Force the context `c' to be the current context and associate with it
312 * buffer `b'.
313 */
314 GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
315 __DRIdrawablePrivate * driDrawPriv,
316 __DRIdrawablePrivate * driReadPriv)
317 {
318 radeonContextPtr radeon;
319 GLframebuffer *dfb, *rfb;
320
321 if (!driContextPriv) {
322 if (RADEON_DEBUG & DEBUG_DRI)
323 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
324 _mesa_make_current(NULL, NULL, NULL);
325 return GL_TRUE;
326 }
327
328 radeon = (radeonContextPtr) driContextPriv->driverPrivate;
329 dfb = driDrawPriv->driverPrivate;
330 rfb = driReadPriv->driverPrivate;
331
332 if (RADEON_DEBUG & DEBUG_DRI)
333 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, radeon->glCtx);
334
335 driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
336 if (driReadPriv != driDrawPriv)
337 driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
338
339 radeon_make_renderbuffer_current(radeon, dfb);
340
341 _mesa_make_current(radeon->glCtx, dfb, rfb);
342
343 if (radeon->dri.drawable != driDrawPriv) {
344 if (driDrawPriv->swap_interval == (unsigned)-1) {
345 driDrawPriv->vblFlags =
346 (radeon->radeonScreen->irq != 0)
347 ? driGetDefaultVBlankFlags(&radeon->
348 optionCache)
349 : VBLANK_FLAG_NO_IRQ;
350
351 driDrawableInitVBlank(driDrawPriv);
352 }
353 }
354
355 radeon->dri.readable = driReadPriv;
356
357 if (radeon->dri.drawable != driDrawPriv ||
358 radeon->lastStamp != driDrawPriv->lastStamp) {
359 radeon->dri.drawable = driDrawPriv;
360
361 radeonSetCliprects(radeon);
362 r300UpdateViewportOffset(radeon->glCtx);
363 }
364
365 _mesa_update_state(radeon->glCtx);
366
367 radeonUpdatePageFlipping(radeon);
368
369 if (RADEON_DEBUG & DEBUG_DRI)
370 fprintf(stderr, "End %s\n", __FUNCTION__);
371 return GL_TRUE;
372 }
373
374 /* Force the context `c' to be unbound from its buffer.
375 */
376 GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
377 {
378 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
379
380 if (RADEON_DEBUG & DEBUG_DRI)
381 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
382 radeon->glCtx);
383
384 return GL_TRUE;
385 }
386