gallium: Have pipe_buffer_* receive a pipe_screen instead of a pipe_context.
[mesa.git] / src / gallium / winsys / drm / intel / dri / intel_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "utils.h"
29 #include "vblank.h"
30 #include "xmlpool.h"
31
32 #include "intel_context.h"
33 #include "intel_screen.h"
34 #include "intel_batchbuffer.h"
35 #include "intel_swapbuffers.h"
36
37 #include "i830_dri.h"
38 #include "ws_dri_bufpool.h"
39
40 #include "pipe/p_context.h"
41 #include "pipe/p_screen.h"
42 #include "pipe/p_inlines.h"
43 #include "state_tracker/st_public.h"
44 #include "state_tracker/st_cb_fbo.h"
45
46 static void
47 intelCreateSurface(struct intel_screen *intelScreen, struct pipe_winsys *winsys, unsigned handle);
48
49 static void
50 intelCreateSurface(struct intel_screen *intelScreen, struct pipe_winsys *winsys, unsigned handle)
51 {
52 struct pipe_screen *screen = intelScreen->base.screen;
53 struct pipe_texture *texture;
54 struct pipe_texture templat;
55 struct pipe_surface *surface;
56 struct pipe_buffer *buffer;
57 unsigned pitch;
58
59 assert(intelScreen->front.cpp == 4);
60
61 buffer = intel_be_buffer_from_handle(&intelScreen->base,
62 "front", handle);
63
64 if (!buffer)
65 return;
66
67 intelScreen->front.buffer = dri_bo(buffer);
68
69 memset(&templat, 0, sizeof(templat));
70 templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
71 templat.target = PIPE_TEXTURE_2D;
72 templat.last_level = 0;
73 templat.depth[0] = 1;
74 templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
75 templat.width[0] = intelScreen->front.width;
76 templat.height[0] = intelScreen->front.height;
77 pf_get_block(templat.format, &templat.block);
78 pitch = intelScreen->front.pitch;
79
80 texture = screen->texture_blanket(screen,
81 &templat,
82 &pitch,
83 buffer);
84
85 /* Unref the buffer we don't need it anyways */
86 pipe_buffer_reference(screen, &buffer, NULL);
87
88 surface = screen->get_tex_surface(screen,
89 texture,
90 0,
91 0,
92 0,
93 PIPE_BUFFER_USAGE_GPU_WRITE);
94
95 intelScreen->front.texture = texture;
96 intelScreen->front.surface = surface;
97 }
98
99 PUBLIC const char __driConfigOptions[] =
100 DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
101 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
102 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
103 DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
104 // DRI_CONF_FORCE_S3TC_ENABLE(false)
105 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
106 DRI_CONF_SECTION_END DRI_CONF_END;
107
108 const uint __driNConfigOptions = 3;
109
110 #ifdef USE_NEW_INTERFACE
111 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
112 #endif /*USE_NEW_INTERFACE */
113
114 extern const struct dri_extension card_extensions[];
115
116
117
118
119 static void
120 intelPrintDRIInfo(struct intel_screen * intelScreen,
121 __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
122 {
123 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
124 intelScreen->front.size, intelScreen->front.offset,
125 intelScreen->front.pitch);
126 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
127 }
128
129
130 #if 0
131 static void
132 intelPrintSAREA(const drmI830Sarea * sarea)
133 {
134 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
135 sarea->height);
136 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
137 fprintf(stderr,
138 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
139 sarea->front_offset, sarea->front_size,
140 (unsigned) sarea->front_handle);
141 fprintf(stderr,
142 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
143 sarea->back_offset, sarea->back_size,
144 (unsigned) sarea->back_handle);
145 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
146 sarea->depth_offset, sarea->depth_size,
147 (unsigned) sarea->depth_handle);
148 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
149 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
150 fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
151 fprintf(stderr,
152 "SAREA: rotated offset: 0x%08x size: 0x%x\n",
153 sarea->rotated_offset, sarea->rotated_size);
154 fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
155 }
156 #endif
157
158
159 /**
160 * Use the information in the sarea to update the screen parameters
161 * related to screen rotation. Needs to be called locked.
162 */
163 void
164 intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
165 {
166 struct intel_screen *intelScreen = intel_screen(sPriv);
167
168 if (intelScreen->front.map) {
169 drmUnmap(intelScreen->front.map, intelScreen->front.size);
170 intelScreen->front.map = NULL;
171 }
172
173 if (intelScreen->front.buffer)
174 driDeleteBuffers(1, &intelScreen->front.buffer);
175
176 intelScreen->front.width = sarea->width;
177 intelScreen->front.height = sarea->height;
178 intelScreen->front.offset = sarea->front_offset;
179 intelScreen->front.pitch = sarea->pitch * intelScreen->front.cpp;
180 intelScreen->front.size = sarea->front_size;
181 intelScreen->front.handle = sarea->front_handle;
182
183 assert( sarea->front_size >=
184 intelScreen->front.pitch * intelScreen->front.height );
185
186 #if 0 /* JB not important */
187 if (!sarea->front_handle)
188 return;
189
190 if (drmMap(sPriv->fd,
191 sarea->front_handle,
192 intelScreen->front.size,
193 (drmAddress *) & intelScreen->front.map) != 0) {
194 fprintf(stderr, "drmMap(frontbuffer) failed!\n");
195 return;
196 }
197 #endif
198
199 #if 0 /* JB */
200 if (intelScreen->staticPool) {
201 driGenBuffers(intelScreen->staticPool, "static region", 1,
202 &intelScreen->front.buffer, 64,
203 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
204 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
205
206 driBOSetStatic(intelScreen->front.buffer,
207 intelScreen->front.offset,
208 intelScreen->front.pitch * intelScreen->front.height,
209 intelScreen->front.map, 0);
210 }
211 #else
212 if (intelScreen->base.staticPool) {
213 if (intelScreen->front.buffer) {
214 driBOUnReference(intelScreen->front.buffer);
215 pipe_surface_reference(&intelScreen->front.surface, NULL);
216 pipe_texture_reference(&intelScreen->front.texture, NULL);
217 }
218 intelCreateSurface(intelScreen, &intelScreen->base.base, sarea->front_bo_handle);
219 }
220 #endif
221 }
222
223
224 boolean
225 intelCreatePools(__DRIscreenPrivate * sPriv)
226 {
227 //unsigned batchPoolSize = 1024*1024;
228 struct intel_screen *intelScreen = intel_screen(sPriv);
229
230 if (intelScreen->havePools)
231 return GL_TRUE;
232
233 intelScreen->havePools = GL_TRUE;
234
235 intelUpdateScreenRotation(sPriv, intelScreen->sarea);
236
237 return GL_TRUE;
238 }
239
240 static const char *
241 intel_get_name( struct pipe_winsys *winsys )
242 {
243 return "Intel/DRI/ttm";
244 }
245
246 /*
247 * The state tracker (should!) keep track of whether the fake
248 * frontbuffer has been touched by any rendering since the last time
249 * we copied its contents to the real frontbuffer. Our task is easy:
250 */
251 static void
252 intel_flush_frontbuffer( struct pipe_winsys *winsys,
253 struct pipe_surface *surf,
254 void *context_private)
255 {
256 struct intel_context *intel = (struct intel_context *) context_private;
257 __DRIdrawablePrivate *dPriv = intel->driDrawable;
258
259 intelDisplaySurface(dPriv, surf, NULL);
260 }
261
262 static boolean
263 intelInitDriver(__DRIscreenPrivate * sPriv)
264 {
265 struct intel_screen *intelScreen;
266 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
267
268 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
269 (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
270 getProcAddress("glxEnableExtension"));
271 void *const psc = sPriv->psc->screenConfigs;
272
273 if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
274 fprintf(stderr,
275 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
276 return GL_FALSE;
277 }
278
279 /* Allocate the private area */
280 intelScreen = CALLOC_STRUCT(intel_screen);
281 if (!intelScreen)
282 return GL_FALSE;
283
284 /* parse information in __driConfigOptions */
285 driParseOptionInfo(&intelScreen->optionCache,
286 __driConfigOptions, __driNConfigOptions);
287
288 sPriv->private = (void *) intelScreen;
289
290 intelScreen->sarea = (drmI830Sarea *) (((GLubyte *) sPriv->pSAREA) +
291 gDRIPriv->sarea_priv_offset);
292 intelScreen->deviceID = gDRIPriv->deviceID;
293 intelScreen->front.cpp = gDRIPriv->cpp;
294 intelScreen->drmMinor = sPriv->drmMinor;
295
296 assert(gDRIPriv->bitsPerPixel == 16 ||
297 gDRIPriv->bitsPerPixel == 32);
298
299 intelUpdateScreenRotation(sPriv, intelScreen->sarea);
300
301 if (0)
302 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
303
304 if (glx_enable_extension != NULL) {
305 (*glx_enable_extension) (psc, "GLX_SGI_swap_control");
306 (*glx_enable_extension) (psc, "GLX_SGI_video_sync");
307 (*glx_enable_extension) (psc, "GLX_MESA_swap_control");
308 (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
309 (*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
310 }
311
312 intelScreen->base.base.flush_frontbuffer = intel_flush_frontbuffer;
313 intelScreen->base.base.get_name = intel_get_name;
314 intel_be_init_device(&intelScreen->base, sPriv->fd, intelScreen->deviceID);
315
316 return GL_TRUE;
317 }
318
319
320 static void
321 intelDestroyScreen(__DRIscreenPrivate * sPriv)
322 {
323 struct intel_screen *intelScreen = intel_screen(sPriv);
324
325 intel_be_destroy_device(&intelScreen->base);
326 /* intelUnmapScreenRegions(intelScreen); */
327
328 FREE(intelScreen);
329 sPriv->private = NULL;
330 }
331
332
333 /**
334 * This is called when we need to set up GL rendering to a new X window.
335 */
336 static boolean
337 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
338 __DRIdrawablePrivate * driDrawPriv,
339 const __GLcontextModes * visual, boolean isPixmap)
340 {
341 if (isPixmap) {
342 return GL_FALSE; /* not implemented */
343 }
344 else {
345 enum pipe_format colorFormat, depthFormat, stencilFormat;
346 struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer);
347
348 if (!intelfb)
349 return GL_FALSE;
350
351 if (visual->redBits == 5)
352 colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
353 else
354 colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
355
356 if (visual->depthBits == 16)
357 depthFormat = PIPE_FORMAT_Z16_UNORM;
358 else if (visual->depthBits == 24)
359 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
360 else
361 depthFormat = PIPE_FORMAT_NONE;
362
363 if (visual->stencilBits == 8)
364 stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
365 else
366 stencilFormat = PIPE_FORMAT_NONE;
367
368 intelfb->stfb = st_create_framebuffer(visual,
369 colorFormat,
370 depthFormat,
371 stencilFormat,
372 driDrawPriv->w,
373 driDrawPriv->h,
374 (void*) intelfb);
375 if (!intelfb->stfb) {
376 free(intelfb);
377 return GL_FALSE;
378 }
379
380 driDrawPriv->driverPrivate = (void *) intelfb;
381 return GL_TRUE;
382 }
383 }
384
385 static void
386 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
387 {
388 struct intel_framebuffer *intelfb = intel_framebuffer(driDrawPriv);
389 assert(intelfb->stfb);
390 st_unreference_framebuffer(&intelfb->stfb);
391 free(intelfb);
392 }
393
394
395 /**
396 * Get information about previous buffer swaps.
397 */
398 static int
399 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
400 {
401 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
402 || (sInfo == NULL)) {
403 return -1;
404 }
405
406 return 0;
407 }
408
409
410 static void
411 intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
412 unsigned long long offset, int depth, uint pitch)
413 {
414 abort();
415 #if 0
416 struct intel_context *intel = (struct intel_context*)
417 ((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate;
418 struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname);
419 struct st_texture_object *stObj = st_texture_object(tObj);
420
421 if (!stObj)
422 return;
423
424 if (stObj->pt)
425 st->pipe->texture_release(intel->st->pipe, &stObj->pt);
426
427 stObj->imageOverride = GL_TRUE;
428 stObj->depthOverride = depth;
429 stObj->pitchOverride = pitch;
430
431 if (offset)
432 stObj->textureOffset = offset;
433 #endif
434 }
435
436
437 static const struct __DriverAPIRec intelAPI = {
438 .InitDriver = intelInitDriver,
439 .DestroyScreen = intelDestroyScreen,
440 .CreateContext = intelCreateContext,
441 .DestroyContext = intelDestroyContext,
442 .CreateBuffer = intelCreateBuffer,
443 .DestroyBuffer = intelDestroyBuffer,
444 .SwapBuffers = intelSwapBuffers,
445 .MakeCurrent = intelMakeCurrent,
446 .UnbindContext = intelUnbindContext,
447 .GetSwapInfo = intelGetSwapInfo,
448 .GetMSC = driGetMSC32,
449 .WaitForMSC = driWaitForMSC32,
450 .WaitForSBC = NULL,
451 .SwapBuffersMSC = NULL,
452 .CopySubBuffer = intelCopySubBuffer,
453 .setTexOffset = intelSetTexOffset,
454 };
455
456
457 static __GLcontextModes *
458 intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
459 unsigned stencil_bits, boolean have_back_buffer)
460 {
461 __GLcontextModes *modes;
462 __GLcontextModes *m;
463 unsigned num_modes;
464 unsigned depth_buffer_factor;
465 unsigned back_buffer_factor;
466 GLenum fb_format;
467 GLenum fb_type;
468
469 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
470 * support pageflipping at all.
471 */
472 static const GLenum back_buffer_modes[] = {
473 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
474 };
475
476 uint8_t depth_bits_array[3];
477 uint8_t stencil_bits_array[3];
478 uint8_t msaa_samples_array[1];
479
480
481 depth_bits_array[0] = 0;
482 depth_bits_array[1] = depth_bits;
483 depth_bits_array[2] = depth_bits;
484 msaa_samples_array[0] = 0;
485
486 /* Just like with the accumulation buffer, always provide some modes
487 * with a stencil buffer. It will be a sw fallback, but some apps won't
488 * care about that.
489 */
490 stencil_bits_array[0] = 0;
491 stencil_bits_array[1] = 0;
492 if (depth_bits == 24)
493 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
494
495 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
496
497 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
498 back_buffer_factor = (have_back_buffer) ? 3 : 1;
499
500 num_modes = depth_buffer_factor * back_buffer_factor * 4;
501
502 if (pixel_bits == 16) {
503 fb_format = GL_RGB;
504 fb_type = GL_UNSIGNED_SHORT_5_6_5;
505 }
506 else {
507 fb_format = GL_BGRA;
508 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
509 }
510
511 modes =
512 (*dri_interface->createContextModes) (num_modes,
513 sizeof(__GLcontextModes));
514 m = modes;
515 if (!driFillInModes(&m, fb_format, fb_type,
516 depth_bits_array, stencil_bits_array,
517 depth_buffer_factor, back_buffer_modes,
518 back_buffer_factor, msaa_samples_array, 1, GLX_TRUE_COLOR)) {
519 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
520 __LINE__);
521 return NULL;
522 }
523 if (!driFillInModes(&m, fb_format, fb_type,
524 depth_bits_array, stencil_bits_array,
525 depth_buffer_factor, back_buffer_modes,
526 back_buffer_factor, msaa_samples_array, 1, GLX_DIRECT_COLOR)) {
527 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
528 __LINE__);
529 return NULL;
530 }
531
532 /* Mark the visual as slow if there are "fake" stencil bits.
533 */
534 for (m = modes; m != NULL; m = m->next) {
535 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
536 m->visualRating = GLX_SLOW_CONFIG;
537 }
538 }
539
540 return modes;
541 }
542
543
544 /**
545 * This is the bootstrap function for the driver. libGL supplies all of the
546 * requisite information about the system, and the driver initializes itself.
547 * This routine also fills in the linked list pointed to by \c driver_modes
548 * with the \c __GLcontextModes that the driver can support for windows or
549 * pbuffers.
550 *
551 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
552 * failure.
553 */
554 PUBLIC void *
555 __driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
556 __DRIscreen * psc,
557 const __GLcontextModes * modes,
558 const __DRIversion * ddx_version,
559 const __DRIversion * dri_version,
560 const __DRIversion * drm_version,
561 const __DRIframebuffer * frame_buffer,
562 drmAddress pSAREA, int fd,
563 int internal_api_version,
564 const __DRIinterfaceMethods * interface,
565 __GLcontextModes ** driver_modes)
566 {
567 __DRIscreenPrivate *psp;
568 static const __DRIversion ddx_expected = { 1, 7, 0 };
569 static const __DRIversion dri_expected = { 4, 0, 0 };
570 static const __DRIversion drm_expected = { 1, 7, 0 };
571
572 dri_interface = interface;
573
574 if (!driCheckDriDdxDrmVersions2("i915",
575 dri_version, &dri_expected,
576 ddx_version, &ddx_expected,
577 drm_version, &drm_expected)) {
578 return NULL;
579 }
580
581 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
582 ddx_version, dri_version, drm_version,
583 frame_buffer, pSAREA, fd,
584 internal_api_version, &intelAPI);
585
586 if (psp != NULL) {
587 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
588 *driver_modes = intelFillInModes(dri_priv->cpp * 8,
589 (dri_priv->cpp == 2) ? 16 : 24,
590 (dri_priv->cpp == 2) ? 0 : 8, 1);
591
592 /* Calling driInitExtensions here, with a NULL context pointer,
593 * does not actually enable the extensions. It just makes sure
594 * that all the dispatch offsets for all the extensions that
595 * *might* be enables are known. This is needed because the
596 * dispatch offsets need to be known when _mesa_context_create
597 * is called, but we can't enable the extensions until we have a
598 * context pointer.
599 *
600 * Hello chicken. Hello egg. How are you two today?
601 */
602 driInitExtensions(NULL, card_extensions, GL_FALSE);
603 }
604
605 return (void *) psp;
606 }
607