i915: Pulled in changes from i915tex
[mesa.git] / src / gallium / winsys / dri / intel / 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_batchpool.h"
36 #include "intel_swapbuffers.h"
37 #include "intel_winsys.h"
38
39 #include "i830_dri.h"
40 #include "ws_dri_bufpool.h"
41
42 #include "pipe/p_context.h"
43 #include "state_tracker/st_public.h"
44 #include "state_tracker/st_cb_fbo.h"
45
46
47
48 PUBLIC const char __driConfigOptions[] =
49 DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
50 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
51 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
52 DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
53 DRI_CONF_FORCE_S3TC_ENABLE(false)
54 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
55 DRI_CONF_SECTION_END DRI_CONF_END;
56
57 const uint __driNConfigOptions = 4;
58
59 #ifdef USE_NEW_INTERFACE
60 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
61 #endif /*USE_NEW_INTERFACE */
62
63 extern const struct dri_extension card_extensions[];
64
65
66
67
68 static void
69 intelPrintDRIInfo(struct intel_screen * intelScreen,
70 __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
71 {
72 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
73 intelScreen->front.size, intelScreen->front.offset,
74 intelScreen->front.pitch);
75 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
76 }
77
78
79 #if 0
80 static void
81 intelPrintSAREA(const drmI830Sarea * sarea)
82 {
83 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
84 sarea->height);
85 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
86 fprintf(stderr,
87 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
88 sarea->front_offset, sarea->front_size,
89 (unsigned) sarea->front_handle);
90 fprintf(stderr,
91 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
92 sarea->back_offset, sarea->back_size,
93 (unsigned) sarea->back_handle);
94 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
95 sarea->depth_offset, sarea->depth_size,
96 (unsigned) sarea->depth_handle);
97 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
98 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
99 fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
100 fprintf(stderr,
101 "SAREA: rotated offset: 0x%08x size: 0x%x\n",
102 sarea->rotated_offset, sarea->rotated_size);
103 fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
104 }
105 #endif
106
107
108 /**
109 * Use the information in the sarea to update the screen parameters
110 * related to screen rotation. Needs to be called locked.
111 */
112 void
113 intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
114 {
115 struct intel_screen *intelScreen = intel_screen(sPriv);
116
117 if (intelScreen->front.map) {
118 drmUnmap(intelScreen->front.map, intelScreen->front.size);
119 intelScreen->front.map = NULL;
120 }
121
122 if (intelScreen->front.buffer)
123 driDeleteBuffers(1, &intelScreen->front.buffer);
124
125 intelScreen->front.width = sarea->width;
126 intelScreen->front.height = sarea->height;
127 intelScreen->front.offset = sarea->front_offset;
128 intelScreen->front.pitch = sarea->pitch * intelScreen->front.cpp;
129 intelScreen->front.size = sarea->front_size;
130 intelScreen->front.handle = sarea->front_handle;
131
132 assert( sarea->front_size >=
133 intelScreen->front.pitch * intelScreen->front.height );
134
135 #if 0 /* JB not important */
136 if (!sarea->front_handle)
137 return;
138
139 if (drmMap(sPriv->fd,
140 sarea->front_handle,
141 intelScreen->front.size,
142 (drmAddress *) & intelScreen->front.map) != 0) {
143 fprintf(stderr, "drmMap(frontbuffer) failed!\n");
144 return;
145 }
146 #endif
147
148 #if 0 /* JB */
149 if (intelScreen->staticPool) {
150 driGenBuffers(intelScreen->staticPool, "static region", 1,
151 &intelScreen->front.buffer, 64,
152 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
153 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
154
155 driBOSetStatic(intelScreen->front.buffer,
156 intelScreen->front.offset,
157 intelScreen->front.pitch * intelScreen->front.height,
158 intelScreen->front.map, 0);
159 }
160 #else
161 if (intelScreen->staticPool) {
162 if (intelScreen->front.buffer)
163 driBOUnReference(intelScreen->front.buffer);
164 driGenBuffers(intelScreen->staticPool, "front", 1, &intelScreen->front.buffer, 0, 0, 0);
165 driBOSetReferenced(intelScreen->front.buffer, sarea->front_bo_handle);
166 }
167 #endif
168 }
169
170
171 boolean
172 intelCreatePools(__DRIscreenPrivate * sPriv)
173 {
174 //unsigned batchPoolSize = 1024*1024;
175 struct intel_screen *intelScreen = intel_screen(sPriv);
176
177 if (intelScreen->havePools)
178 return GL_TRUE;
179
180 #if 0 /* ZZZ JB fix this */
181 intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
182 if (!intelScreen->staticPool)
183 return GL_FALSE;
184
185 batchPoolSize /= BATCH_SZ;
186 intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
187 DRM_BO_FLAG_EXE |
188 DRM_BO_FLAG_MEM_TT |
189 DRM_BO_FLAG_MEM_LOCAL,
190 BATCH_SZ,
191 batchPoolSize, 5);
192 if (!intelScreen->batchPool) {
193 fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
194 return GL_FALSE;
195 }
196 #else
197 intelScreen->staticPool = driDRMPoolInit(sPriv->fd);
198 intelScreen->batchPool = driSlabPoolInit(sPriv->fd,
199 DRM_BO_FLAG_EXE |
200 DRM_BO_FLAG_MEM_TT,
201 DRM_BO_FLAG_EXE |
202 DRM_BO_FLAG_MEM_TT,
203 4096, //intelScreen->maxBatchSize,
204 1, 40, 16*16384, 0,
205 intelScreen->fMan);
206 #endif
207 intelScreen->havePools = GL_TRUE;
208
209 intelUpdateScreenRotation(sPriv, intelScreen->sarea);
210
211 return GL_TRUE;
212 }
213
214
215 static boolean
216 intelInitDriver(__DRIscreenPrivate * sPriv)
217 {
218 struct intel_screen *intelScreen;
219 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
220
221 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
222 (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
223 getProcAddress("glxEnableExtension"));
224 void *const psc = sPriv->psc->screenConfigs;
225
226 if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
227 fprintf(stderr,
228 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
229 return GL_FALSE;
230 }
231
232 /* Allocate the private area */
233 intelScreen = CALLOC_STRUCT(intel_screen);
234 if (!intelScreen)
235 return GL_FALSE;
236
237 /* parse information in __driConfigOptions */
238 driParseOptionInfo(&intelScreen->optionCache,
239 __driConfigOptions, __driNConfigOptions);
240
241 sPriv->private = (void *) intelScreen;
242
243 intelScreen->sarea = (drmI830Sarea *) (((GLubyte *) sPriv->pSAREA) +
244 gDRIPriv->sarea_priv_offset);
245 intelScreen->deviceID = gDRIPriv->deviceID;
246 intelScreen->front.cpp = gDRIPriv->cpp;
247 intelScreen->drmMinor = sPriv->drmMinor;
248
249 assert(gDRIPriv->bitsPerPixel == 16 ||
250 gDRIPriv->bitsPerPixel == 32);
251
252 intelUpdateScreenRotation(sPriv, intelScreen->sarea);
253
254 if (0)
255 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
256
257 if (glx_enable_extension != NULL) {
258 (*glx_enable_extension) (psc, "GLX_SGI_swap_control");
259 (*glx_enable_extension) (psc, "GLX_SGI_video_sync");
260 (*glx_enable_extension) (psc, "GLX_MESA_swap_control");
261 (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
262 (*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
263 }
264
265
266
267 #if 1 // ZZZ JB
268 intelScreen->mgr = driFenceMgrTTMInit(sPriv->fd);
269 if (!intelScreen->mgr) {
270 fprintf(stderr, "Failed to create fence manager.\n");
271 return GL_FALSE;
272 }
273
274 intelScreen->fMan = driInitFreeSlabManager(10, 10);
275 if (!intelScreen->fMan) {
276 fprintf(stderr, "Failed to create free slab manager.\n");
277 return GL_FALSE;
278 }
279
280 if (!intelCreatePools(sPriv))
281 return GL_FALSE;
282 #endif
283
284 intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd, intelScreen->fMan);
285
286 return GL_TRUE;
287 }
288
289
290 static void
291 intelDestroyScreen(__DRIscreenPrivate * sPriv)
292 {
293 struct intel_screen *intelScreen = intel_screen(sPriv);
294
295 /* intelUnmapScreenRegions(intelScreen); */
296
297 if (intelScreen->havePools) {
298 driPoolTakeDown(intelScreen->staticPool);
299 driPoolTakeDown(intelScreen->batchPool);
300 }
301 FREE(intelScreen);
302 sPriv->private = NULL;
303 }
304
305
306 /**
307 * This is called when we need to set up GL rendering to a new X window.
308 */
309 static boolean
310 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
311 __DRIdrawablePrivate * driDrawPriv,
312 const __GLcontextModes * visual, boolean isPixmap)
313 {
314 if (isPixmap) {
315 return GL_FALSE; /* not implemented */
316 }
317 else {
318 enum pipe_format colorFormat, depthFormat, stencilFormat;
319 struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer);
320
321 if (!intelfb)
322 return GL_FALSE;
323
324 if (visual->redBits == 5)
325 colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
326 else
327 colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
328
329 if (visual->depthBits == 16)
330 depthFormat = PIPE_FORMAT_Z16_UNORM;
331 else if (visual->depthBits == 24)
332 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
333 else
334 depthFormat = PIPE_FORMAT_NONE;
335
336 if (visual->stencilBits == 8)
337 stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
338 else
339 stencilFormat = PIPE_FORMAT_NONE;
340
341 intelfb->stfb = st_create_framebuffer(visual,
342 colorFormat,
343 depthFormat,
344 stencilFormat,
345 driDrawPriv->w,
346 driDrawPriv->h,
347 (void*) intelfb);
348 if (!intelfb->stfb) {
349 free(intelfb);
350 return GL_FALSE;
351 }
352
353 driDrawPriv->driverPrivate = (void *) intelfb;
354 return GL_TRUE;
355 }
356 }
357
358 static void
359 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
360 {
361 struct intel_framebuffer *intelfb = intel_framebuffer(driDrawPriv);
362 assert(intelfb->stfb);
363 st_unreference_framebuffer(&intelfb->stfb);
364 free(intelfb);
365 }
366
367
368 /**
369 * Get information about previous buffer swaps.
370 */
371 static int
372 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
373 {
374 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
375 || (sInfo == NULL)) {
376 return -1;
377 }
378
379 return 0;
380 }
381
382
383 static void
384 intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
385 unsigned long long offset, int depth, uint pitch)
386 {
387 abort();
388 #if 0
389 struct intel_context *intel = (struct intel_context*)
390 ((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate;
391 struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname);
392 struct st_texture_object *stObj = st_texture_object(tObj);
393
394 if (!stObj)
395 return;
396
397 if (stObj->pt)
398 st->pipe->texture_release(intel->st->pipe, &stObj->pt);
399
400 stObj->imageOverride = GL_TRUE;
401 stObj->depthOverride = depth;
402 stObj->pitchOverride = pitch;
403
404 if (offset)
405 stObj->textureOffset = offset;
406 #endif
407 }
408
409
410 static const struct __DriverAPIRec intelAPI = {
411 .InitDriver = intelInitDriver,
412 .DestroyScreen = intelDestroyScreen,
413 .CreateContext = intelCreateContext,
414 .DestroyContext = intelDestroyContext,
415 .CreateBuffer = intelCreateBuffer,
416 .DestroyBuffer = intelDestroyBuffer,
417 .SwapBuffers = intelSwapBuffers,
418 .MakeCurrent = intelMakeCurrent,
419 .UnbindContext = intelUnbindContext,
420 .GetSwapInfo = intelGetSwapInfo,
421 .GetMSC = driGetMSC32,
422 .WaitForMSC = driWaitForMSC32,
423 .WaitForSBC = NULL,
424 .SwapBuffersMSC = NULL,
425 .CopySubBuffer = intelCopySubBuffer,
426 .setTexOffset = intelSetTexOffset,
427 };
428
429
430 static __GLcontextModes *
431 intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
432 unsigned stencil_bits, boolean have_back_buffer)
433 {
434 __GLcontextModes *modes;
435 __GLcontextModes *m;
436 unsigned num_modes;
437 unsigned depth_buffer_factor;
438 unsigned back_buffer_factor;
439 GLenum fb_format;
440 GLenum fb_type;
441
442 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
443 * support pageflipping at all.
444 */
445 static const GLenum back_buffer_modes[] = {
446 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
447 };
448
449 u_int8_t depth_bits_array[3];
450 u_int8_t stencil_bits_array[3];
451
452
453 depth_bits_array[0] = 0;
454 depth_bits_array[1] = depth_bits;
455 depth_bits_array[2] = depth_bits;
456
457 /* Just like with the accumulation buffer, always provide some modes
458 * with a stencil buffer. It will be a sw fallback, but some apps won't
459 * care about that.
460 */
461 stencil_bits_array[0] = 0;
462 stencil_bits_array[1] = 0;
463 if (depth_bits == 24)
464 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
465
466 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
467
468 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
469 back_buffer_factor = (have_back_buffer) ? 3 : 1;
470
471 num_modes = depth_buffer_factor * back_buffer_factor * 4;
472
473 if (pixel_bits == 16) {
474 fb_format = GL_RGB;
475 fb_type = GL_UNSIGNED_SHORT_5_6_5;
476 }
477 else {
478 fb_format = GL_BGRA;
479 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
480 }
481
482 modes =
483 (*dri_interface->createContextModes) (num_modes,
484 sizeof(__GLcontextModes));
485 m = modes;
486 if (!driFillInModes(&m, fb_format, fb_type,
487 depth_bits_array, stencil_bits_array,
488 depth_buffer_factor, back_buffer_modes,
489 back_buffer_factor, GLX_TRUE_COLOR)) {
490 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
491 __LINE__);
492 return NULL;
493 }
494 if (!driFillInModes(&m, fb_format, fb_type,
495 depth_bits_array, stencil_bits_array,
496 depth_buffer_factor, back_buffer_modes,
497 back_buffer_factor, GLX_DIRECT_COLOR)) {
498 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
499 __LINE__);
500 return NULL;
501 }
502
503 /* Mark the visual as slow if there are "fake" stencil bits.
504 */
505 for (m = modes; m != NULL; m = m->next) {
506 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
507 m->visualRating = GLX_SLOW_CONFIG;
508 }
509 }
510
511 return modes;
512 }
513
514
515 /**
516 * This is the bootstrap function for the driver. libGL supplies all of the
517 * requisite information about the system, and the driver initializes itself.
518 * This routine also fills in the linked list pointed to by \c driver_modes
519 * with the \c __GLcontextModes that the driver can support for windows or
520 * pbuffers.
521 *
522 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
523 * failure.
524 */
525 PUBLIC void *
526 __driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
527 __DRIscreen * psc,
528 const __GLcontextModes * modes,
529 const __DRIversion * ddx_version,
530 const __DRIversion * dri_version,
531 const __DRIversion * drm_version,
532 const __DRIframebuffer * frame_buffer,
533 drmAddress pSAREA, int fd,
534 int internal_api_version,
535 const __DRIinterfaceMethods * interface,
536 __GLcontextModes ** driver_modes)
537 {
538 __DRIscreenPrivate *psp;
539 static const __DRIversion ddx_expected = { 1, 7, 0 };
540 static const __DRIversion dri_expected = { 4, 0, 0 };
541 static const __DRIversion drm_expected = { 1, 7, 0 };
542
543 dri_interface = interface;
544
545 if (!driCheckDriDdxDrmVersions2("i915",
546 dri_version, &dri_expected,
547 ddx_version, &ddx_expected,
548 drm_version, &drm_expected)) {
549 return NULL;
550 }
551
552 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
553 ddx_version, dri_version, drm_version,
554 frame_buffer, pSAREA, fd,
555 internal_api_version, &intelAPI);
556
557 if (psp != NULL) {
558 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
559 *driver_modes = intelFillInModes(dri_priv->cpp * 8,
560 (dri_priv->cpp == 2) ? 16 : 24,
561 (dri_priv->cpp == 2) ? 0 : 8, 1);
562
563 /* Calling driInitExtensions here, with a NULL context pointer,
564 * does not actually enable the extensions. It just makes sure
565 * that all the dispatch offsets for all the extensions that
566 * *might* be enables are known. This is needed because the
567 * dispatch offsets need to be known when _mesa_context_create
568 * is called, but we can't enable the extensions until we have a
569 * context pointer.
570 *
571 * Hello chicken. Hello egg. How are you two today?
572 */
573 driInitExtensions(NULL, card_extensions, GL_FALSE);
574 }
575
576 return (void *) psp;
577 }
578