Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / i810 / i810context.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, 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 PRECISION INSIGHT 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 /*
29  * Authors:
30  *   Keith Whitwell <keith@tungstengraphics.com>
31  *
32  */
33
34
35 #include "main/glheader.h"
36 #include "main/context.h"
37 #include "main/simple_list.h"
38 #include "main/imports.h"
39 #include "main/points.h"
40
41 #include "swrast/swrast.h"
42 #include "swrast_setup/swrast_setup.h"
43 #include "tnl/tnl.h"
44 #include "vbo/vbo.h"
45
46 #include "tnl/t_pipeline.h"
47
48 #include "drivers/common/driverfuncs.h"
49
50 #include "i810screen.h"
51 #include "i810_dri.h"
52
53 #include "i810state.h"
54 #include "i810tex.h"
55 #include "i810span.h"
56 #include "i810tris.h"
57 #include "i810vb.h"
58 #include "i810ioctl.h"
59
60 #include "drirenderbuffer.h"
61 #include "utils.h"
62
63 #ifndef I810_DEBUG
64 int I810_DEBUG = (0);
65 #endif
66
67 PUBLIC const char __driConfigOptions[] = { 0 };
68 const GLuint __driNConfigOptions = 0;
69
70 static const GLubyte *i810GetString( struct gl_context *ctx, GLenum name )
71 {
72    static char buffer[128];
73
74    switch (name) {
75    case GL_VENDOR:
76       return (GLubyte *)"Keith Whitwell";
77    case GL_RENDERER: {
78       i810ContextPtr imesa = I810_CONTEXT(ctx);
79       const char * chipset;
80       
81       switch (imesa->i810Screen->deviceID) {
82       case PCI_CHIP_I810:       chipset = "i810"; break;
83       case PCI_CHIP_I810_DC100: chipset = "i810 DC-100"; break;
84       case PCI_CHIP_I810_E:     chipset = "i810E"; break;
85       case PCI_CHIP_I815:       chipset = "i815"; break;
86       default:                  chipset = "Unknown i810-class Chipset"; break;
87       }
88
89       (void) driGetRendererString( buffer, chipset, 0 );
90       return (GLubyte *) buffer;
91    }
92    default:
93       return 0;
94    }
95 }
96
97 static void i810BufferSize(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
98 {
99    GET_CURRENT_CONTEXT(ctx);
100    i810ContextPtr imesa = I810_CONTEXT(ctx);
101
102    /* Need to lock to make sure the driDrawable is uptodate.  This
103     * information is used to resize Mesa's software buffers, so it has
104     * to be correct.
105     */
106    LOCK_HARDWARE(imesa);
107    *width = imesa->driDrawable->w;
108    *height = imesa->driDrawable->h;
109    UNLOCK_HARDWARE(imesa);
110 }
111
112 /* Extension strings exported by the i810 driver.
113  */
114 static const struct dri_extension card_extensions[] =
115 {
116     { "GL_ARB_multitexture",               NULL },
117     { "GL_ARB_texture_env_add",            NULL },
118     { "GL_ARB_texture_env_combine",        NULL },
119     { "GL_ARB_texture_env_crossbar",       NULL },
120     { "GL_ARB_texture_mirrored_repeat",    NULL },
121     { "GL_EXT_stencil_wrap",               NULL },
122     { "GL_EXT_texture_edge_clamp",         NULL },
123     { "GL_EXT_texture_env_combine",        NULL },
124     { "GL_EXT_texture_lod_bias",           NULL },
125     { "GL_EXT_texture_rectangle",          NULL },
126     { "GL_MESA_ycbcr_texture",             NULL },
127     { "GL_NV_blend_square",                NULL },
128     { NULL,                                NULL }
129 };
130
131 extern const struct tnl_pipeline_stage _i810_render_stage;
132
133 static const struct tnl_pipeline_stage *i810_pipeline[] = {
134    &_tnl_vertex_transform_stage,
135    &_tnl_normal_transform_stage,
136    &_tnl_lighting_stage,
137    &_tnl_fog_coordinate_stage,
138    &_tnl_texgen_stage,
139    &_tnl_texture_transform_stage,
140                                 /* REMOVE: point attenuation stage */
141 #if 1
142    &_i810_render_stage,         /* ADD: unclipped rastersetup-to-dma */
143 #endif
144    &_tnl_render_stage,
145    0,
146 };
147
148 static const struct dri_debug_control debug_control[] =
149 {
150     { "fall",  DEBUG_FALLBACKS },
151     { "tex",   DEBUG_TEXTURE },
152     { "ioctl", DEBUG_IOCTL },
153     { "prim",  DEBUG_PRIMS },
154     { "vert",  DEBUG_VERTS },
155     { "state", DEBUG_STATE },
156     { "verb",  DEBUG_VERBOSE },
157     { "dri",   DEBUG_DRI },
158     { "dma",   DEBUG_DMA },
159     { "san",   DEBUG_SANITY },
160     { "sync",  DEBUG_SYNC },
161     { "sleep", DEBUG_SLEEP },
162     { NULL,    0 }
163 };
164
165 GLboolean
166 i810CreateContext( gl_api api,
167                    const struct gl_config *mesaVis,
168                    __DRIcontext *driContextPriv,
169                    void *sharedContextPrivate )
170 {
171    struct gl_context *ctx, *shareCtx;
172    i810ContextPtr imesa;
173    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
174    i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
175    I810SAREAPtr saPriv = (I810SAREAPtr)
176       (((GLubyte *)sPriv->pSAREA) + i810Screen->sarea_priv_offset);
177    struct dd_function_table functions;
178
179    /* Allocate i810 context */
180    imesa = (i810ContextPtr) CALLOC_STRUCT(i810_context_t);
181    if (!imesa) {
182       return GL_FALSE;
183    }
184
185    driContextPriv->driverPrivate = imesa;
186
187    imesa->i810Screen = i810Screen;
188    imesa->driScreen = sPriv;
189    imesa->sarea = saPriv;
190    imesa->glBuffer = NULL;
191
192    /* Init default driver functions then plug in our I810-specific functions
193     * (the texture functions are especially important)
194     */
195    _mesa_init_driver_functions( &functions );
196    i810InitIoctlFuncs( &functions );
197    i810InitTextureFuncs( &functions );
198
199
200    /* Allocate the Mesa context */
201    if (sharedContextPrivate)
202       shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
203    else
204       shareCtx = NULL;
205    imesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx,
206                                        &functions, (void*) imesa);
207    if (!imesa->glCtx) {
208       FREE(imesa);
209       return GL_FALSE;
210    }
211
212    (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
213    make_empty_list( & imesa->swapped );
214    
215    imesa->nr_heaps = 1;
216    imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa,
217             i810Screen->textureSize,
218             12,
219             I810_NR_TEX_REGIONS,
220             imesa->sarea->texList,
221             (unsigned *) & imesa->sarea->texAge, /* XXX we shouldn't cast! */
222             & imesa->swapped,
223             sizeof( struct i810_texture_object_t ),
224             (destroy_texture_object_t *) i810DestroyTexObj );
225
226
227
228    /* Set the maximum texture size small enough that we can guarentee
229     * that both texture units can bind a maximal texture and have them
230     * in memory at once.
231     */
232
233
234
235    ctx = imesa->glCtx;
236    ctx->Const.MaxTextureUnits = 2;
237    ctx->Const.MaxTextureImageUnits = 2;
238    ctx->Const.MaxTextureCoordUnits = 2;
239
240
241    /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
242     * FIXME: packed, but they're not in Intel graphics hardware.
243     */
244    driCalculateMaxTextureLevels( imesa->texture_heaps,
245                                  imesa->nr_heaps,
246                                  & ctx->Const,
247                                  4,
248                                  11, /* max 2D texture size is 2048x2048 */
249                                  0,  /* 3D textures unsupported */
250                                  0,  /* cube textures unsupported. */
251                                  0,  /* texture rectangles unsupported. */
252                                  12,
253                                  GL_FALSE,
254                                  0 );
255
256    ctx->Const.MinLineWidth = 1.0;
257    ctx->Const.MinLineWidthAA = 1.0;
258    ctx->Const.MaxLineWidth = 3.0;
259    ctx->Const.MaxLineWidthAA = 3.0;
260    ctx->Const.LineWidthGranularity = 1.0;
261
262    ctx->Const.MinPointSize = 1.0;
263    ctx->Const.MinPointSizeAA = 1.0;
264    ctx->Const.MaxPointSize = 3.0;
265    ctx->Const.MaxPointSizeAA = 3.0;
266    ctx->Const.PointSizeGranularity = 1.0;
267
268    /* reinitialize the context point state.
269     * It depend on constants in __struct gl_contextRec::Const
270     */
271    _mesa_init_point(ctx);
272
273    ctx->Driver.GetBufferSize = i810BufferSize;
274    ctx->Driver.GetString = i810GetString;
275
276    /* Who owns who?
277     */
278    ctx->DriverCtx = (void *) imesa;
279    imesa->glCtx = ctx;
280
281    /* Initialize the software rasterizer and helper modules.
282     */
283    _swrast_CreateContext( ctx );
284    _vbo_CreateContext( ctx );
285    _tnl_CreateContext( ctx );
286    _swsetup_CreateContext( ctx );
287
288    /* Install the customized pipeline:
289     */
290    _tnl_destroy_pipeline( ctx );
291    _tnl_install_pipeline( ctx, i810_pipeline );
292
293    /* Configure swrast and T&L to match hardware characteristics:
294     */
295    _swrast_allow_pixel_fog( ctx, GL_FALSE );
296    _swrast_allow_vertex_fog( ctx, GL_TRUE );
297    _tnl_allow_pixel_fog( ctx, GL_FALSE );
298    _tnl_allow_vertex_fog( ctx, GL_TRUE );
299
300    /* Dri stuff
301     */
302    imesa->hHWContext = driContextPriv->hHWContext;
303    imesa->driFd = sPriv->fd;
304    imesa->driHwLock = &sPriv->pSAREA->lock;
305
306    imesa->stipple_in_hw = 1;
307    imesa->RenderIndex = ~0;
308    imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
309    imesa->upload_cliprects = GL_TRUE;
310
311    imesa->CurrentTexObj[0] = 0;
312    imesa->CurrentTexObj[1] = 0;
313
314    _math_matrix_ctr( &imesa->ViewportMatrix );
315
316    driInitExtensions( ctx, card_extensions, GL_TRUE );
317    /* XXX these should really go right after _mesa_init_driver_functions() */
318    i810InitStateFuncs( ctx );
319    i810InitTriFuncs( ctx );
320    i810InitSpanFuncs( ctx );
321    i810InitVB( ctx );
322    i810InitState( ctx );
323
324 #if DO_DEBUG
325    I810_DEBUG  = driParseDebugString( getenv( "I810_DEBUG" ),
326                                       debug_control );
327    I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
328                                       debug_control );
329 #endif
330
331    return GL_TRUE;
332 }
333
334 void
335 i810DestroyContext(__DRIcontext *driContextPriv)
336 {
337    i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
338
339    assert(imesa); /* should never be null */
340    if (imesa) {
341       GLboolean   release_texture_heaps;
342
343
344       release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1);
345       _swsetup_DestroyContext( imesa->glCtx );
346       _tnl_DestroyContext( imesa->glCtx );
347       _vbo_DestroyContext( imesa->glCtx );
348       _swrast_DestroyContext( imesa->glCtx );
349
350       i810FreeVB( imesa->glCtx );
351
352       /* free the Mesa context */
353       imesa->glCtx->DriverCtx = NULL;
354       _mesa_destroy_context(imesa->glCtx);
355       if ( release_texture_heaps ) {
356          /* This share group is about to go away, free our private
357           * texture object data.
358           */
359          unsigned int i;
360
361          for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
362             driDestroyTextureHeap( imesa->texture_heaps[ i ] );
363             imesa->texture_heaps[ i ] = NULL;
364          }
365
366          assert( is_empty_list( & imesa->swapped ) );
367       }
368
369       FREE(imesa);
370    }
371 }
372
373
374 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
375 {
376    __DRIdrawable *dPriv = imesa->driDrawable;
377
378    imesa->numClipRects = dPriv->numClipRects;
379    imesa->pClipRects = dPriv->pClipRects;
380    imesa->drawX = dPriv->x;
381    imesa->drawY = dPriv->y;
382
383    i810EmitDrawingRectangle( imesa );
384    imesa->upload_cliprects = GL_TRUE;
385 }
386
387
388 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
389 {
390    __DRIdrawable *dPriv = imesa->driDrawable;
391
392    if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
393    {
394       imesa->numClipRects = dPriv->numClipRects;
395       imesa->pClipRects = dPriv->pClipRects;
396       imesa->drawX = dPriv->x;
397       imesa->drawY = dPriv->y;
398    } else {
399       imesa->numClipRects = dPriv->numBackClipRects;
400       imesa->pClipRects = dPriv->pBackClipRects;
401       imesa->drawX = dPriv->backX;
402       imesa->drawY = dPriv->backY;
403    }
404
405    i810EmitDrawingRectangle( imesa );
406    imesa->upload_cliprects = GL_TRUE;
407 }
408
409
410 static void i810XMesaWindowMoved( i810ContextPtr imesa )
411 {
412    /* Determine current color drawing buffer */
413    switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0]) {
414    case BUFFER_FRONT_LEFT:
415       i810XMesaSetFrontClipRects( imesa );
416       break;
417    case BUFFER_BACK_LEFT:
418       i810XMesaSetBackClipRects( imesa );
419       break;
420    default:
421       /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
422       i810XMesaSetFrontClipRects( imesa );
423    }
424 }
425
426
427 GLboolean
428 i810UnbindContext(__DRIcontext *driContextPriv)
429 {
430    i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
431    if (imesa) {
432       imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
433       if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
434       if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
435    }
436
437    return GL_TRUE;
438 }
439
440
441 GLboolean
442 i810MakeCurrent(__DRIcontext *driContextPriv,
443                 __DRIdrawable *driDrawPriv,
444                 __DRIdrawable *driReadPriv)
445 {
446    if (driContextPriv) {
447       i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
448
449       /* Shouldn't the readbuffer be stored also?
450        */
451       imesa->driDrawable = driDrawPriv;
452
453       _mesa_make_current(imesa->glCtx,
454                          (struct gl_framebuffer *) driDrawPriv->driverPrivate,
455                          (struct gl_framebuffer *) driReadPriv->driverPrivate);
456
457       /* Are these necessary?
458        */
459       i810XMesaWindowMoved( imesa );
460    }
461    else {
462       _mesa_make_current(NULL, NULL, NULL);
463    }
464
465    return GL_TRUE;
466 }
467
468 static void
469 i810UpdatePageFlipping( i810ContextPtr imesa )
470 {
471    struct gl_context *ctx = imesa->glCtx;
472    int front = 0;
473
474    /* Determine current color drawing buffer */
475    switch (ctx->DrawBuffer->_ColorDrawBufferIndexes[0]) {
476    case BUFFER_FRONT_LEFT:
477       front = 1;
478       break;
479    case BUFFER_BACK_LEFT:
480       front = 0;
481       break;
482    default:
483       return;
484    }
485
486    if ( imesa->sarea->pf_current_page == 1 ) 
487      front ^= 1;
488
489    driFlipRenderbuffers(ctx->WinSysDrawBuffer, front);
490    
491    if (front) {
492       imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
493    } else {
494       imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
495    }
496
497    imesa->dirty |= I810_UPLOAD_BUFFERS;
498 }
499
500 void i810GetLock( i810ContextPtr imesa, GLuint flags )
501 {
502    __DRIdrawable *dPriv = imesa->driDrawable;
503    __DRIscreen *sPriv = imesa->driScreen;
504    I810SAREAPtr sarea = imesa->sarea;
505    int me = imesa->hHWContext;
506    unsigned i;
507
508    drmGetLock(imesa->driFd, imesa->hHWContext, flags);
509
510    /* If the window moved, may need to set a new cliprect now.
511     *
512     * NOTE: This releases and regains the hw lock, so all state
513     * checking must be done *after* this call:
514     */
515    DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
516
517
518    /* If we lost context, need to dump all registers to hardware.
519     * Note that we don't care about 2d contexts, even if they perform
520     * accelerated commands, so the DRI locking in the X server is even
521     * more broken than usual.
522     */
523    if (sarea->ctxOwner != me) {
524       driUpdateFramebufferSize(imesa->glCtx, dPriv);
525       imesa->upload_cliprects = GL_TRUE;
526       imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
527       if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
528       if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
529       sarea->ctxOwner = me;
530    }
531
532    /* Shared texture managment - if another client has played with
533     * texture space, figure out which if any of our textures have been
534     * ejected, and update our global LRU.
535     */ 
536    for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
537       DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
538    }
539
540    if (imesa->lastStamp != dPriv->lastStamp) {
541       i810UpdatePageFlipping( imesa );
542       i810XMesaWindowMoved( imesa );
543       imesa->lastStamp = dPriv->lastStamp;
544    }
545 }
546
547
548 void
549 i810SwapBuffers( __DRIdrawable *dPriv )
550 {
551    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
552       i810ContextPtr imesa;
553       struct gl_context *ctx;
554       imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
555       ctx = imesa->glCtx;
556       if (ctx->Visual.doubleBufferMode) {
557          _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
558          if ( imesa->sarea->pf_active ) {
559             i810PageFlip( dPriv );
560          } else {
561             i810CopyBuffer( dPriv );
562          }
563       }
564    }
565    else {
566       /* XXX this shouldn't be an error but we can't handle it for now */
567       _mesa_problem(NULL, "i810SwapBuffers: drawable has no context!\n");
568    }
569 }
570