radeon: avoid page flip code in DRI2
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_common_context.c
1 /**************************************************************************
2
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
5 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6
7 The Weather Channel (TM) funded Tungsten Graphics to develop the
8 initial release of the Radeon 8500 driver under the XFree86 license.
9 This notice must be preserved.
10
11 All Rights Reserved.
12
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to
18 permit persons to whom the Software is furnished to do so, subject to
19 the following conditions:
20
21 The above copyright notice and this permission notice (including the
22 next paragraph) shall be included in all copies or substantial
23 portions of the Software.
24
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
29 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33 **************************************************************************/
34
35 #include "radeon_common.h"
36 #include "xmlpool.h" /* for symbolic values of enum-type options */
37 #include "utils.h"
38 #include "drirenderbuffer.h"
39 #include "vblank.h"
40 #include "main/state.h"
41
42 #define DRIVER_DATE "20090101"
43
44 #ifndef RADEON_DEBUG
45 int RADEON_DEBUG = (0);
46 #endif
47
48 /* Return various strings for glGetString().
49 */
50 static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
51 {
52 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
53 static char buffer[128];
54
55 switch (name) {
56 case GL_VENDOR:
57 if (IS_R300_CLASS(radeon->radeonScreen))
58 return (GLubyte *) "DRI R300 Project";
59 else
60 return (GLubyte *) "Tungsten Graphics, Inc.";
61
62 case GL_RENDERER:
63 {
64 unsigned offset;
65 GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
66 radeon->radeonScreen->AGPMode;
67 const char* chipname;
68
69 if (IS_R300_CLASS(radeon->radeonScreen))
70 chipname = "R300";
71 else if (IS_R200_CLASS(radeon->radeonScreen))
72 chipname = "R200";
73 else
74 chipname = "R100";
75
76 offset = driGetRendererString(buffer, chipname, DRIVER_DATE,
77 agp_mode);
78
79 if (IS_R300_CLASS(radeon->radeonScreen)) {
80 sprintf(&buffer[offset], " %sTCL",
81 (radeon->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)
82 ? "" : "NO-");
83 } else {
84 sprintf(&buffer[offset], " %sTCL",
85 !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
86 ? "" : "NO-");
87 }
88
89 if (radeon->radeonScreen->driScreen->dri2.enabled)
90 strcat(buffer, " DRI2");
91
92 return (GLubyte *) buffer;
93 }
94
95 default:
96 return NULL;
97 }
98 }
99
100 /* Initialize the driver's misc functions.
101 */
102 static void radeonInitDriverFuncs(struct dd_function_table *functions)
103 {
104 functions->GetString = radeonGetString;
105 }
106
107 /**
108 * Create and initialize all common fields of the context,
109 * including the Mesa context itself.
110 */
111 GLboolean radeonInitContext(radeonContextPtr radeon,
112 struct dd_function_table* functions,
113 const __GLcontextModes * glVisual,
114 __DRIcontextPrivate * driContextPriv,
115 void *sharedContextPrivate)
116 {
117 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
118 radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
119 GLcontext* ctx;
120 GLcontext* shareCtx;
121 int fthrottle_mode;
122
123 /* Fill in additional standard functions. */
124 radeonInitDriverFuncs(functions);
125
126 radeon->radeonScreen = screen;
127 /* Allocate and initialize the Mesa context */
128 if (sharedContextPrivate)
129 shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
130 else
131 shareCtx = NULL;
132 radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
133 functions, (void *)radeon);
134 if (!radeon->glCtx)
135 return GL_FALSE;
136
137 ctx = radeon->glCtx;
138 driContextPriv->driverPrivate = radeon;
139
140 /* DRI fields */
141 radeon->dri.context = driContextPriv;
142 radeon->dri.screen = sPriv;
143 radeon->dri.drawable = NULL;
144 radeon->dri.readable = NULL;
145 radeon->dri.hwContext = driContextPriv->hHWContext;
146 radeon->dri.hwLock = &sPriv->pSAREA->lock;
147 radeon->dri.fd = sPriv->fd;
148 radeon->dri.drmMinor = sPriv->drm_version.minor;
149
150 radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
151 screen->sarea_priv_offset);
152
153 /* Setup IRQs */
154 fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
155 radeon->iw.irq_seq = -1;
156 radeon->irqsEmitted = 0;
157 radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
158 radeon->radeonScreen->irq);
159
160 radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
161
162 if (!radeon->do_irqs)
163 fprintf(stderr,
164 "IRQ's not enabled, falling back to %s: %d %d\n",
165 radeon->do_usleeps ? "usleeps" : "busy waits",
166 fthrottle_mode, radeon->radeonScreen->irq);
167
168 (*sPriv->systemTime->getUST) (&radeon->swap_ust);
169
170 return GL_TRUE;
171 }
172
173 /**
174 * Cleanup common context fields.
175 * Called by r200DestroyContext/r300DestroyContext
176 */
177 void radeonCleanupContext(radeonContextPtr radeon)
178 {
179 #ifdef RADEON_BO_TRACK
180 FILE *track;
181 #endif
182 struct radeon_renderbuffer *rb;
183 GLframebuffer *fb;
184
185 /* free the Mesa context */
186 _mesa_destroy_context(radeon->glCtx);
187
188 fb = (void*)radeon->dri.drawable->driverPrivate;
189 rb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
190 if (rb && rb->bo) {
191 radeon_bo_unref(rb->bo);
192 rb->bo = NULL;
193 }
194 rb = (void *)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
195 if (rb && rb->bo) {
196 radeon_bo_unref(rb->bo);
197 rb->bo = NULL;
198 }
199 rb = (void *)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
200 if (rb && rb->bo) {
201 radeon_bo_unref(rb->bo);
202 rb->bo = NULL;
203 }
204 fb = (void*)radeon->dri.readable->driverPrivate;
205 rb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
206 if (rb && rb->bo) {
207 radeon_bo_unref(rb->bo);
208 rb->bo = NULL;
209 }
210 rb = (void *)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
211 if (rb && rb->bo) {
212 radeon_bo_unref(rb->bo);
213 rb->bo = NULL;
214 }
215 rb = (void *)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
216 if (rb && rb->bo) {
217 radeon_bo_unref(rb->bo);
218 rb->bo = NULL;
219 }
220
221 /* _mesa_destroy_context() might result in calls to functions that
222 * depend on the DriverCtx, so don't set it to NULL before.
223 *
224 * radeon->glCtx->DriverCtx = NULL;
225 */
226
227
228
229 /* free the option cache */
230 driDestroyOptionCache(&radeon->optionCache);
231
232 rcommonDestroyCmdBuf(radeon);
233
234 if (radeon->state.scissor.pClipRects) {
235 FREE(radeon->state.scissor.pClipRects);
236 radeon->state.scissor.pClipRects = 0;
237 }
238 #ifdef RADEON_BO_TRACK
239 track = fopen("/tmp/tracklog", "w");
240 if (track) {
241 radeon_tracker_print(&radeon->radeonScreen->bom->tracker, track);
242 fclose(track);
243 }
244 #endif
245 }
246
247 /* Force the context `c' to be unbound from its buffer.
248 */
249 GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
250 {
251 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
252
253 if (RADEON_DEBUG & DEBUG_DRI)
254 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
255 radeon->glCtx);
256
257 return GL_TRUE;
258 }
259
260
261 static void
262 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon,
263 GLframebuffer *draw)
264 {
265 /* if radeon->fake */
266 struct radeon_renderbuffer *rb;
267
268 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
269 if (!rb->bo) {
270 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
271 radeon->radeonScreen->frontOffset,
272 0,
273 0,
274 RADEON_GEM_DOMAIN_VRAM,
275 0);
276 }
277 rb->cpp = radeon->radeonScreen->cpp;
278 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
279 }
280 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
281 if (!rb->bo) {
282 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
283 radeon->radeonScreen->backOffset,
284 0,
285 0,
286 RADEON_GEM_DOMAIN_VRAM,
287 0);
288 }
289 rb->cpp = radeon->radeonScreen->cpp;
290 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
291 }
292 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
293 if (!rb->bo) {
294 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
295 radeon->radeonScreen->depthOffset,
296 0,
297 0,
298 RADEON_GEM_DOMAIN_VRAM,
299 0);
300 }
301 rb->cpp = radeon->radeonScreen->cpp;
302 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
303 }
304 if ((rb = (void *)draw->Attachment[BUFFER_STENCIL].Renderbuffer)) {
305 if (!rb->bo) {
306 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
307 radeon->radeonScreen->depthOffset,
308 0,
309 0,
310 RADEON_GEM_DOMAIN_VRAM,
311 0);
312 }
313 rb->cpp = radeon->radeonScreen->cpp;
314 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
315 }
316 }
317
318 static void
319 radeon_make_renderbuffer_current(radeonContextPtr radeon,
320 GLframebuffer *draw)
321 {
322 int size = 4096*4096*4;
323 /* if radeon->fake */
324 struct radeon_renderbuffer *rb;
325
326 if (radeon->radeonScreen->kernel_mm) {
327 radeon_make_kernel_renderbuffer_current(radeon, draw);
328 return;
329 }
330
331
332 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
333 if (!rb->bo) {
334 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
335 radeon->radeonScreen->frontOffset +
336 radeon->radeonScreen->fbLocation,
337 size,
338 4096,
339 RADEON_GEM_DOMAIN_VRAM,
340 0);
341 }
342 rb->cpp = radeon->radeonScreen->cpp;
343 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
344 }
345 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
346 if (!rb->bo) {
347 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
348 radeon->radeonScreen->backOffset +
349 radeon->radeonScreen->fbLocation,
350 size,
351 4096,
352 RADEON_GEM_DOMAIN_VRAM,
353 0);
354 }
355 rb->cpp = radeon->radeonScreen->cpp;
356 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
357 }
358 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
359 if (!rb->bo) {
360 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
361 radeon->radeonScreen->depthOffset +
362 radeon->radeonScreen->fbLocation,
363 size,
364 4096,
365 RADEON_GEM_DOMAIN_VRAM,
366 0);
367 }
368 rb->cpp = radeon->radeonScreen->cpp;
369 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
370 }
371 if ((rb = (void *)draw->Attachment[BUFFER_STENCIL].Renderbuffer)) {
372 if (!rb->bo) {
373 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
374 radeon->radeonScreen->depthOffset +
375 radeon->radeonScreen->fbLocation,
376 size,
377 4096,
378 RADEON_GEM_DOMAIN_VRAM,
379 0);
380 }
381 rb->cpp = radeon->radeonScreen->cpp;
382 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
383 }
384 }
385
386
387 void
388 radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
389 {
390 unsigned int attachments[10];
391 __DRIbuffer *buffers;
392 __DRIscreen *screen;
393 struct radeon_renderbuffer *rb;
394 int i, count;
395 GLframebuffer *draw;
396 radeonContextPtr radeon;
397
398 if (RADEON_DEBUG & DEBUG_DRI)
399 fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
400
401 draw = drawable->driverPrivate;
402 screen = context->driScreenPriv;
403 radeon = (radeonContextPtr) context->driverPrivate;
404 i = 0;
405 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
406 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
407 }
408 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
409 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
410 }
411 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
412 attachments[i++] = __DRI_BUFFER_DEPTH;
413 }
414
415 buffers = (*screen->dri2.loader->getBuffers)(drawable,
416 &drawable->w,
417 &drawable->h,
418 attachments, i,
419 &count,
420 drawable->loaderPrivate);
421 if (buffers == NULL)
422 return;
423
424 /* set one cliprect to cover the whole drawable */
425 drawable->x = 0;
426 drawable->y = 0;
427 drawable->backX = 0;
428 drawable->backY = 0;
429 drawable->numClipRects = 1;
430 drawable->pClipRects[0].x1 = 0;
431 drawable->pClipRects[0].y1 = 0;
432 drawable->pClipRects[0].x2 = drawable->w;
433 drawable->pClipRects[0].y2 = drawable->h;
434 drawable->numBackClipRects = 1;
435 drawable->pBackClipRects[0].x1 = 0;
436 drawable->pBackClipRects[0].y1 = 0;
437 drawable->pBackClipRects[0].x2 = drawable->w;
438 drawable->pBackClipRects[0].y2 = drawable->h;
439 for (i = 0; i < count; i++) {
440 switch (buffers[i].attachment) {
441 case __DRI_BUFFER_FRONT_LEFT:
442 rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
443 if (rb->bo) {
444 radeon_bo_unref(rb->bo);
445 rb->bo = NULL;
446 }
447 rb->cpp = buffers[i].cpp;
448 rb->pitch = buffers[i].pitch;
449 rb->width = drawable->w;
450 rb->height = drawable->h;
451 rb->has_surface = 0;
452 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
453 buffers[i].name,
454 0,
455 0,
456 RADEON_GEM_DOMAIN_VRAM,
457 buffers[i].flags);
458 if (rb->bo == NULL) {
459 fprintf(stderr, "failled to attach front %d\n",
460 buffers[i].name);
461 }
462 break;
463 case __DRI_BUFFER_BACK_LEFT:
464 rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
465 if (rb->bo) {
466 radeon_bo_unref(rb->bo);
467 rb->bo = NULL;
468 }
469 rb->cpp = buffers[i].cpp;
470 rb->pitch = buffers[i].pitch;
471 rb->width = drawable->w;
472 rb->height = drawable->h;
473 rb->has_surface = 0;
474 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
475 buffers[i].name,
476 0,
477 0,
478 RADEON_GEM_DOMAIN_VRAM,
479 buffers[i].flags);
480 break;
481 case __DRI_BUFFER_DEPTH:
482 rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer;
483 if (rb->bo) {
484 radeon_bo_unref(rb->bo);
485 rb->bo = NULL;
486 }
487 rb->cpp = buffers[i].cpp;
488 rb->pitch = buffers[i].pitch;
489 rb->width = drawable->w;
490 rb->height = drawable->h;
491 rb->has_surface = 0;
492 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
493 buffers[i].name,
494 0,
495 0,
496 RADEON_GEM_DOMAIN_VRAM,
497 buffers[i].flags);
498 break;
499 case __DRI_BUFFER_STENCIL:
500 break;
501 case __DRI_BUFFER_ACCUM:
502 default:
503 fprintf(stderr,
504 "unhandled buffer attach event, attacment type %d\n",
505 buffers[i].attachment);
506 return;
507 }
508 }
509 radeon = (radeonContextPtr) context->driverPrivate;
510 driUpdateFramebufferSize(radeon->glCtx, drawable);
511 }
512
513 /* Force the context `c' to be the current context and associate with it
514 * buffer `b'.
515 */
516 GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
517 __DRIdrawablePrivate * driDrawPriv,
518 __DRIdrawablePrivate * driReadPriv)
519 {
520 radeonContextPtr radeon;
521 GLframebuffer *dfb, *rfb;
522
523 if (!driContextPriv) {
524 if (RADEON_DEBUG & DEBUG_DRI)
525 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
526 _mesa_make_current(NULL, NULL, NULL);
527 return GL_TRUE;
528 }
529 radeon = (radeonContextPtr) driContextPriv->driverPrivate;
530 dfb = driDrawPriv->driverPrivate;
531 rfb = driReadPriv->driverPrivate;
532
533 if (driContextPriv->driScreenPriv->dri2.enabled) {
534 radeon_update_renderbuffers(driContextPriv, driDrawPriv);
535 if (driDrawPriv != driReadPriv)
536 radeon_update_renderbuffers(driContextPriv, driReadPriv);
537 radeon->state.color.rrb =
538 (void *)dfb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
539 radeon->state.depth.rrb =
540 (void *)dfb->Attachment[BUFFER_DEPTH].Renderbuffer;
541 } else {
542 radeon_make_renderbuffer_current(radeon, dfb);
543 }
544
545
546 if (RADEON_DEBUG & DEBUG_DRI)
547 fprintf(stderr, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__, radeon->glCtx, dfb, rfb);
548
549 driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
550 if (driReadPriv != driDrawPriv)
551 driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
552
553
554
555 _mesa_make_current(radeon->glCtx, dfb, rfb);
556
557 if (radeon->dri.drawable != driDrawPriv) {
558 if (driDrawPriv->swap_interval == (unsigned)-1) {
559 driDrawPriv->vblFlags =
560 (radeon->radeonScreen->irq != 0)
561 ? driGetDefaultVBlankFlags(&radeon->
562 optionCache)
563 : VBLANK_FLAG_NO_IRQ;
564
565 driDrawableInitVBlank(driDrawPriv);
566 }
567 }
568
569 radeon->dri.readable = driReadPriv;
570
571 if (radeon->dri.drawable != driDrawPriv ||
572 radeon->lastStamp != driDrawPriv->lastStamp) {
573 radeon->dri.drawable = driDrawPriv;
574
575 radeonSetCliprects(radeon);
576 radeon->vtbl.update_viewport_offset(radeon->glCtx);
577 }
578
579 _mesa_update_state(radeon->glCtx);
580
581 if (!driContextPriv->driScreenPriv->dri2.enabled) {
582 radeonUpdatePageFlipping(radeon);
583 }
584
585 if (RADEON_DEBUG & DEBUG_DRI)
586 fprintf(stderr, "End %s\n", __FUNCTION__);
587 return GL_TRUE;
588 }
589