swrast.c revision 64b1dc44495890cbc2c7c5509cb830264020998c
1/*
2 * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23/*
24 * DRI software rasterizer
25 *
26 * This is the mesa swrast module packaged into a DRI driver structure.
27 *
28 * The front-buffer is allocated by the loader. The loader provides read/write
29 * callbacks for access to the front-buffer. The driver uses a scratch row for
30 * front-buffer rendering to avoid repeated calls to the loader.
31 *
32 * The back-buffer is allocated by the driver and is private.
33 */
34
35#include "main/api_exec.h"
36#include "main/context.h"
37#include "main/extensions.h"
38#include "main/formats.h"
39#include "main/framebuffer.h"
40#include "main/imports.h"
41#include "main/renderbuffer.h"
42#include "main/version.h"
43#include "main/vtxfmt.h"
44#include "swrast/swrast.h"
45#include "swrast/s_renderbuffer.h"
46#include "swrast_setup/swrast_setup.h"
47#include "tnl/tnl.h"
48#include "tnl/t_context.h"
49#include "tnl/t_pipeline.h"
50#include "vbo/vbo.h"
51#include "drivers/common/driverfuncs.h"
52#include "drivers/common/meta.h"
53#include "utils.h"
54
55#include "main/teximage.h"
56#include "main/texformat.h"
57#include "main/texstate.h"
58
59#include "swrast_priv.h"
60#include "swrast/s_context.h"
61
62const __DRIextension **__driDriverGetExtensions_swrast(void);
63
64const char const *swrast_vendor_string = "Mesa Project";
65const char const *swrast_renderer_string = "Software Rasterizer";
66
67/**
68 * Screen and config-related functions
69 */
70
71static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
72				GLint texture_format, __DRIdrawable *dPriv)
73{
74    struct dri_context *dri_ctx;
75    int x, y, w, h;
76    __DRIscreen *sPriv = dPriv->driScreenPriv;
77    struct gl_texture_object *texObj;
78    struct gl_texture_image *texImage;
79    struct swrast_texture_image *swImage;
80    uint32_t internalFormat;
81    mesa_format texFormat;
82
83    dri_ctx = pDRICtx->driverPrivate;
84
85    internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);
86
87    texObj = _mesa_get_current_tex_object(&dri_ctx->Base, target);
88    texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0);
89    swImage = swrast_texture_image(texImage);
90
91    _mesa_lock_texture(&dri_ctx->Base, texObj);
92
93    sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate);
94
95    if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
96	texFormat = MESA_FORMAT_B8G8R8X8_UNORM;
97    else
98	texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
99
100    _mesa_init_teximage_fields(&dri_ctx->Base, texImage,
101			       w, h, 1, 0, internalFormat, texFormat);
102
103    sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer,
104				   dPriv->loaderPrivate);
105
106    _mesa_unlock_texture(&dri_ctx->Base, texObj);
107}
108
109static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
110			       __DRIdrawable *dPriv)
111{
112    swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
113}
114
115static const __DRItexBufferExtension swrastTexBufferExtension = {
116   .base = { __DRI_TEX_BUFFER, 3 },
117
118   .setTexBuffer        = swrastSetTexBuffer,
119   .setTexBuffer2       = swrastSetTexBuffer2,
120   .releaseTexBuffer    = NULL,
121};
122
123
124static int
125swrast_query_renderer_integer(__DRIscreen *psp, int param,
126			       unsigned int *value)
127{
128   switch (param) {
129   case __DRI2_RENDERER_VENDOR_ID:
130   case __DRI2_RENDERER_DEVICE_ID:
131      /* Return 0xffffffff for both vendor and device id */
132      value[0] = 0xffffffff;
133      return 0;
134   case __DRI2_RENDERER_ACCELERATED:
135      value[0] = 0;
136      return 0;
137   case __DRI2_RENDERER_VIDEO_MEMORY: {
138      /* XXX: Do we want to return the full amount of system memory ? */
139      const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
140      const long system_page_size = sysconf(_SC_PAGE_SIZE);
141
142      if (system_memory_pages <= 0 || system_page_size <= 0)
143         return -1;
144
145      const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
146         * (uint64_t) system_page_size;
147
148      const unsigned system_memory_megabytes =
149         (unsigned) (system_memory_bytes / (1024 * 1024));
150
151      value[0] = system_memory_megabytes;
152      return 0;
153   }
154   case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
155      /**
156       * XXX: Perhaps we should return 1 ?
157       * See issue #7 from the spec, currently UNRESOLVED.
158       */
159      value[0] = 0;
160      return 0;
161   default:
162      return driQueryRendererIntegerCommon(psp, param, value);
163   }
164}
165
166static int
167swrast_query_renderer_string(__DRIscreen *psp, int param, const char **value)
168{
169   switch (param) {
170   case __DRI2_RENDERER_VENDOR_ID:
171      value[0] = swrast_vendor_string;
172      return 0;
173   case __DRI2_RENDERER_DEVICE_ID:
174      value[0] = swrast_renderer_string;
175      return 0;
176   default:
177      return -1;
178   }
179}
180
181static const __DRI2rendererQueryExtension swrast_query_renderer_extension = {
182   .base = { __DRI2_RENDERER_QUERY, 1 },
183
184   .queryInteger        = swrast_query_renderer_integer,
185   .queryString         = swrast_query_renderer_string
186};
187
188static const __DRIextension *dri_screen_extensions[] = {
189    &swrastTexBufferExtension.base,
190    &swrast_query_renderer_extension.base,
191    NULL
192};
193
194static __DRIconfig **
195swrastFillInModes(__DRIscreen *psp,
196		  unsigned pixel_bits, unsigned depth_bits,
197		  unsigned stencil_bits, GLboolean have_back_buffer)
198{
199    __DRIconfig **configs;
200    unsigned depth_buffer_factor;
201    unsigned back_buffer_factor;
202    mesa_format format;
203
204    /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
205     * support pageflipping at all.
206     */
207    static const GLenum back_buffer_modes[] = {
208	GLX_NONE, GLX_SWAP_UNDEFINED_OML
209    };
210
211    uint8_t depth_bits_array[4];
212    uint8_t stencil_bits_array[4];
213    uint8_t msaa_samples_array[1];
214
215    (void) psp;
216    (void) have_back_buffer;
217
218    depth_bits_array[0] = 0;
219    depth_bits_array[1] = 0;
220    depth_bits_array[2] = depth_bits;
221    depth_bits_array[3] = depth_bits;
222
223    /* Just like with the accumulation buffer, always provide some modes
224     * with a stencil buffer.
225     */
226    stencil_bits_array[0] = 0;
227    stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
228    stencil_bits_array[2] = 0;
229    stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
230
231    msaa_samples_array[0] = 0;
232
233    depth_buffer_factor = 4;
234    back_buffer_factor = 2;
235
236    switch (pixel_bits) {
237    case 16:
238	format = MESA_FORMAT_B5G6R5_UNORM;
239	break;
240    case 24:
241        format = MESA_FORMAT_B8G8R8X8_UNORM;
242	break;
243    case 32:
244	format = MESA_FORMAT_B8G8R8A8_UNORM;
245	break;
246    default:
247	fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
248		pixel_bits);
249	return NULL;
250    }
251
252    configs = driCreateConfigs(format,
253			       depth_bits_array, stencil_bits_array,
254			       depth_buffer_factor, back_buffer_modes,
255			       back_buffer_factor, msaa_samples_array, 1,
256			       GL_TRUE);
257    if (configs == NULL) {
258	fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
259		__LINE__);
260	return NULL;
261    }
262
263    return configs;
264}
265
266static const __DRIconfig **
267dri_init_screen(__DRIscreen * psp)
268{
269    __DRIconfig **configs16, **configs24, **configs32;
270
271    TRACE;
272
273    psp->max_gl_compat_version = 21;
274    psp->max_gl_es1_version = 11;
275    psp->max_gl_es2_version = 20;
276
277    psp->extensions = dri_screen_extensions;
278
279    configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
280    configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
281    configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
282
283    configs24 = driConcatConfigs(configs16, configs24);
284    configs32 = driConcatConfigs(configs24, configs32);
285
286    return (const __DRIconfig **)configs32;
287}
288
289static void
290dri_destroy_screen(__DRIscreen * sPriv)
291{
292    TRACE;
293    (void) sPriv;
294}
295
296
297/**
298 * Framebuffer and renderbuffer-related functions.
299 */
300
301static GLuint
302choose_pixel_format(const struct gl_config *v)
303{
304    int depth = v->rgbBits;
305
306    if (depth == 32
307	&& v->redMask   == 0xff0000
308	&& v->greenMask == 0x00ff00
309	&& v->blueMask  == 0x0000ff)
310	return PF_A8R8G8B8;
311    else if (depth == 24
312	     && v->redMask   == 0xff0000
313	     && v->greenMask == 0x00ff00
314	     && v->blueMask  == 0x0000ff)
315	return PF_X8R8G8B8;
316    else if (depth == 16
317	     && v->redMask   == 0xf800
318	     && v->greenMask == 0x07e0
319	     && v->blueMask  == 0x001f)
320	return PF_R5G6B5;
321    else if (depth == 8
322	     && v->redMask   == 0x07
323	     && v->greenMask == 0x38
324	     && v->blueMask  == 0xc0)
325	return PF_R3G3B2;
326
327    _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
328    return 0;
329}
330
331static void
332swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
333{
334    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
335
336    TRACE;
337
338    free(xrb->Base.Buffer);
339    _mesa_delete_renderbuffer(ctx, rb);
340}
341
342/* see bytes_per_line in libGL */
343static INLINE int
344bytes_per_line(unsigned pitch_bits, unsigned mul)
345{
346   unsigned mask = mul - 1;
347
348   return ((pitch_bits + mask) & ~mask) / 8;
349}
350
351static GLboolean
352swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
353			   GLenum internalFormat, GLuint width, GLuint height)
354{
355    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
356
357    TRACE;
358
359    (void) ctx;
360    (void) internalFormat;
361
362    xrb->Base.Buffer = NULL;
363    rb->Width = width;
364    rb->Height = height;
365    xrb->pitch = bytes_per_line(width * xrb->bpp, 32);
366
367    return GL_TRUE;
368}
369
370static GLboolean
371swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
372			  GLenum internalFormat, GLuint width, GLuint height)
373{
374    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
375
376    TRACE;
377
378    free(xrb->Base.Buffer);
379
380    swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
381
382    xrb->Base.Buffer = malloc(height * xrb->pitch);
383
384    return GL_TRUE;
385}
386
387static struct dri_swrast_renderbuffer *
388swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv,
389			GLboolean front)
390{
391    struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
392    struct gl_renderbuffer *rb;
393    GLuint pixel_format;
394
395    TRACE;
396
397    if (!xrb)
398	return NULL;
399
400    rb = &xrb->Base.Base;
401
402    _mesa_init_renderbuffer(rb, 0);
403
404    pixel_format = choose_pixel_format(visual);
405
406    xrb->dPriv = dPriv;
407    xrb->Base.Base.Delete = swrast_delete_renderbuffer;
408    if (front) {
409        rb->AllocStorage = swrast_alloc_front_storage;
410    }
411    else {
412	rb->AllocStorage = swrast_alloc_back_storage;
413    }
414
415    switch (pixel_format) {
416    case PF_A8R8G8B8:
417	rb->Format = MESA_FORMAT_B8G8R8A8_UNORM;
418	rb->InternalFormat = GL_RGBA;
419	rb->_BaseFormat = GL_RGBA;
420	xrb->bpp = 32;
421	break;
422    case PF_X8R8G8B8:
423	rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; /* XXX */
424	rb->InternalFormat = GL_RGB;
425	rb->_BaseFormat = GL_RGB;
426	xrb->bpp = 32;
427	break;
428    case PF_R5G6B5:
429	rb->Format = MESA_FORMAT_B5G6R5_UNORM;
430	rb->InternalFormat = GL_RGB;
431	rb->_BaseFormat = GL_RGB;
432	xrb->bpp = 16;
433	break;
434    case PF_R3G3B2:
435	rb->Format = MESA_FORMAT_B2G3R3_UNORM;
436	rb->InternalFormat = GL_RGB;
437	rb->_BaseFormat = GL_RGB;
438	xrb->bpp = 8;
439	break;
440    default:
441	free(xrb);
442	return NULL;
443    }
444
445    return xrb;
446}
447
448static void
449swrast_map_renderbuffer(struct gl_context *ctx,
450			struct gl_renderbuffer *rb,
451			GLuint x, GLuint y, GLuint w, GLuint h,
452			GLbitfield mode,
453			GLubyte **out_map,
454			GLint *out_stride)
455{
456   struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
457   GLubyte *map = xrb->Base.Buffer;
458   int cpp = _mesa_get_format_bytes(rb->Format);
459   int stride = rb->Width * cpp;
460
461   if (rb->AllocStorage == swrast_alloc_front_storage) {
462      __DRIdrawable *dPriv = xrb->dPriv;
463      __DRIscreen *sPriv = dPriv->driScreenPriv;
464
465      xrb->map_mode = mode;
466      xrb->map_x = x;
467      xrb->map_y = y;
468      xrb->map_w = w;
469      xrb->map_h = h;
470
471      stride = w * cpp;
472      xrb->Base.Buffer = malloc(h * stride);
473
474      sPriv->swrast_loader->getImage(dPriv, x, rb->Height - y - h, w, h,
475				     (char *) xrb->Base.Buffer,
476				     dPriv->loaderPrivate);
477
478      *out_map = xrb->Base.Buffer + (h - 1) * stride;
479      *out_stride = -stride;
480      return;
481   }
482
483   ASSERT(xrb->Base.Buffer);
484
485   if (rb->AllocStorage == swrast_alloc_back_storage) {
486      map += (rb->Height - 1) * stride;
487      stride = -stride;
488   }
489
490   map += (GLsizei)y * stride;
491   map += (GLsizei)x * cpp;
492
493   *out_map = map;
494   *out_stride = stride;
495}
496
497static void
498swrast_unmap_renderbuffer(struct gl_context *ctx,
499			  struct gl_renderbuffer *rb)
500{
501   struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
502
503   if (rb->AllocStorage == swrast_alloc_front_storage) {
504      __DRIdrawable *dPriv = xrb->dPriv;
505      __DRIscreen *sPriv = dPriv->driScreenPriv;
506
507      if (xrb->map_mode & GL_MAP_WRITE_BIT) {
508	 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW,
509					xrb->map_x, xrb->map_y,
510					xrb->map_w, xrb->map_h,
511					(char *) xrb->Base.Buffer,
512					dPriv->loaderPrivate);
513      }
514
515      free(xrb->Base.Buffer);
516      xrb->Base.Buffer = NULL;
517   }
518}
519
520static GLboolean
521dri_create_buffer(__DRIscreen * sPriv,
522		  __DRIdrawable * dPriv,
523		  const struct gl_config * visual, GLboolean isPixmap)
524{
525    struct dri_drawable *drawable = NULL;
526    struct gl_framebuffer *fb;
527    struct dri_swrast_renderbuffer *frontrb, *backrb;
528
529    TRACE;
530
531    (void) sPriv;
532    (void) isPixmap;
533
534    drawable = CALLOC_STRUCT(dri_drawable);
535    if (drawable == NULL)
536	goto drawable_fail;
537
538    dPriv->driverPrivate = drawable;
539    drawable->dPriv = dPriv;
540
541    drawable->row = malloc(SWRAST_MAX_WIDTH * 4);
542    if (drawable->row == NULL)
543	goto drawable_fail;
544
545    fb = &drawable->Base;
546
547    /* basic framebuffer setup */
548    _mesa_initialize_window_framebuffer(fb, visual);
549
550    /* add front renderbuffer */
551    frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE);
552    _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base);
553
554    /* add back renderbuffer */
555    if (visual->doubleBufferMode) {
556	backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE);
557	_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base.Base);
558    }
559
560    /* add software renderbuffers */
561    _swrast_add_soft_renderbuffers(fb,
562                                   GL_FALSE, /* color */
563                                   visual->haveDepthBuffer,
564                                   visual->haveStencilBuffer,
565                                   visual->haveAccumBuffer,
566                                   GL_FALSE, /* alpha */
567                                   GL_FALSE /* aux bufs */);
568
569    return GL_TRUE;
570
571drawable_fail:
572
573    if (drawable)
574	free(drawable->row);
575
576    free(drawable);
577
578    return GL_FALSE;
579}
580
581static void
582dri_destroy_buffer(__DRIdrawable * dPriv)
583{
584    TRACE;
585
586    if (dPriv) {
587	struct dri_drawable *drawable = dri_drawable(dPriv);
588	struct gl_framebuffer *fb;
589
590	free(drawable->row);
591
592	fb = &drawable->Base;
593
594	fb->DeletePending = GL_TRUE;
595	_mesa_reference_framebuffer(&fb, NULL);
596    }
597}
598
599static void
600dri_swap_buffers(__DRIdrawable * dPriv)
601{
602    __DRIscreen *sPriv = dPriv->driScreenPriv;
603
604    GET_CURRENT_CONTEXT(ctx);
605
606    struct dri_drawable *drawable = dri_drawable(dPriv);
607    struct gl_framebuffer *fb;
608    struct dri_swrast_renderbuffer *frontrb, *backrb;
609
610    TRACE;
611
612    fb = &drawable->Base;
613
614    frontrb =
615	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
616    backrb =
617	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
618
619    /* check for signle-buffered */
620    if (backrb == NULL)
621	return;
622
623    /* check if swapping currently bound buffer */
624    if (ctx && ctx->DrawBuffer == fb) {
625	/* flush pending rendering */
626	_mesa_notifySwapBuffers(ctx);
627    }
628
629    sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
630				   0, 0,
631				   frontrb->Base.Base.Width,
632				   frontrb->Base.Base.Height,
633				   (char *) backrb->Base.Buffer,
634				   dPriv->loaderPrivate);
635}
636
637
638/**
639 * General device driver functions.
640 */
641
642static void
643get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h )
644{
645    __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv;
646    __DRIscreen *sPriv = dPriv->driScreenPriv;
647    int x, y;
648
649    sPriv->swrast_loader->getDrawableInfo(dPriv,
650					  &x, &y, w, h,
651					  dPriv->loaderPrivate);
652}
653
654static void
655swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb )
656{
657    GLsizei width, height;
658
659    get_window_size(fb, &width, &height);
660    if (fb->Width != width || fb->Height != height) {
661	_mesa_resize_framebuffer(ctx, fb, width, height);
662    }
663}
664
665static const GLubyte *
666get_string(struct gl_context *ctx, GLenum pname)
667{
668    (void) ctx;
669    switch (pname) {
670	case GL_VENDOR:
671	    return (const GLubyte *) swrast_vendor_string;
672	case GL_RENDERER:
673	    return (const GLubyte *) swrast_renderer_string;
674	default:
675	    return NULL;
676    }
677}
678
679static void
680update_state( struct gl_context *ctx, GLuint new_state )
681{
682    /* not much to do here - pass it on */
683    _swrast_InvalidateState( ctx, new_state );
684    _swsetup_InvalidateState( ctx, new_state );
685    _vbo_InvalidateState( ctx, new_state );
686    _tnl_InvalidateState( ctx, new_state );
687}
688
689static void
690viewport(struct gl_context *ctx)
691{
692    struct gl_framebuffer *draw = ctx->WinSysDrawBuffer;
693    struct gl_framebuffer *read = ctx->WinSysReadBuffer;
694
695    swrast_check_and_update_window_size(ctx, draw);
696    swrast_check_and_update_window_size(ctx, read);
697}
698
699static mesa_format swrastChooseTextureFormat(struct gl_context * ctx,
700                                           GLenum target,
701					   GLint internalFormat,
702					   GLenum format,
703					   GLenum type)
704{
705    if (internalFormat == GL_RGB)
706	return MESA_FORMAT_B8G8R8X8_UNORM;
707    return _mesa_choose_tex_format(ctx, target, internalFormat, format, type);
708}
709
710static void
711swrast_init_driver_functions(struct dd_function_table *driver)
712{
713    driver->GetString = get_string;
714    driver->UpdateState = update_state;
715    driver->Viewport = viewport;
716    driver->ChooseTextureFormat = swrastChooseTextureFormat;
717    driver->MapRenderbuffer = swrast_map_renderbuffer;
718    driver->UnmapRenderbuffer = swrast_unmap_renderbuffer;
719}
720
721/**
722 * Context-related functions.
723 */
724
725static GLboolean
726dri_create_context(gl_api api,
727		   const struct gl_config * visual,
728		   __DRIcontext * cPriv,
729		   unsigned major_version,
730		   unsigned minor_version,
731		   uint32_t flags,
732		   bool notify_reset,
733		   unsigned *error,
734		   void *sharedContextPrivate)
735{
736    struct dri_context *ctx = NULL;
737    struct dri_context *share = (struct dri_context *)sharedContextPrivate;
738    struct gl_context *mesaCtx = NULL;
739    struct gl_context *sharedCtx = NULL;
740    struct dd_function_table functions;
741
742    TRACE;
743
744    /* Flag filtering is handled in dri2CreateContextAttribs.
745     */
746    (void) flags;
747
748    ctx = CALLOC_STRUCT(dri_context);
749    if (ctx == NULL) {
750	*error = __DRI_CTX_ERROR_NO_MEMORY;
751	goto context_fail;
752    }
753
754    cPriv->driverPrivate = ctx;
755    ctx->cPriv = cPriv;
756
757    /* build table of device driver functions */
758    _mesa_init_driver_functions(&functions);
759    swrast_init_driver_functions(&functions);
760
761    if (share) {
762	sharedCtx = &share->Base;
763    }
764
765    mesaCtx = &ctx->Base;
766
767    /* basic context setup */
768    if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) {
769	*error = __DRI_CTX_ERROR_NO_MEMORY;
770	goto context_fail;
771    }
772
773    driContextSetFlags(mesaCtx, flags);
774
775    /* do bounds checking to prevent segfaults and server crashes! */
776    mesaCtx->Const.CheckArrayBounds = GL_TRUE;
777
778    /* create module contexts */
779    _swrast_CreateContext( mesaCtx );
780    _vbo_CreateContext( mesaCtx );
781    _tnl_CreateContext( mesaCtx );
782    _swsetup_CreateContext( mesaCtx );
783    _swsetup_Wakeup( mesaCtx );
784
785    /* use default TCL pipeline */
786    {
787       TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
788       tnl->Driver.RunPipeline = _tnl_run_pipeline;
789    }
790
791    _mesa_meta_init(mesaCtx);
792    _mesa_enable_sw_extensions(mesaCtx);
793
794    _mesa_compute_version(mesaCtx);
795
796    _mesa_initialize_dispatch_tables(mesaCtx);
797    _mesa_initialize_vbo_vtxfmt(mesaCtx);
798
799    *error = __DRI_CTX_ERROR_SUCCESS;
800    return GL_TRUE;
801
802context_fail:
803
804    free(ctx);
805
806    return GL_FALSE;
807}
808
809static void
810dri_destroy_context(__DRIcontext * cPriv)
811{
812    TRACE;
813
814    if (cPriv) {
815	struct dri_context *ctx = dri_context(cPriv);
816	struct gl_context *mesaCtx;
817
818	mesaCtx = &ctx->Base;
819
820        _mesa_meta_free(mesaCtx);
821	_swsetup_DestroyContext( mesaCtx );
822	_swrast_DestroyContext( mesaCtx );
823	_tnl_DestroyContext( mesaCtx );
824	_vbo_DestroyContext( mesaCtx );
825	_mesa_destroy_context( mesaCtx );
826    }
827}
828
829static GLboolean
830dri_make_current(__DRIcontext * cPriv,
831		 __DRIdrawable * driDrawPriv,
832		 __DRIdrawable * driReadPriv)
833{
834    struct gl_context *mesaCtx;
835    struct gl_framebuffer *mesaDraw;
836    struct gl_framebuffer *mesaRead;
837    TRACE;
838
839    if (cPriv) {
840	struct dri_context *ctx = dri_context(cPriv);
841	struct dri_drawable *draw;
842	struct dri_drawable *read;
843
844	if (!driDrawPriv || !driReadPriv)
845	    return GL_FALSE;
846
847	draw = dri_drawable(driDrawPriv);
848	read = dri_drawable(driReadPriv);
849	mesaCtx = &ctx->Base;
850	mesaDraw = &draw->Base;
851	mesaRead = &read->Base;
852
853	/* check for same context and buffer */
854	if (mesaCtx == _mesa_get_current_context()
855	    && mesaCtx->DrawBuffer == mesaDraw
856	    && mesaCtx->ReadBuffer == mesaRead) {
857	    return GL_TRUE;
858	}
859
860	_glapi_check_multithread();
861
862	swrast_check_and_update_window_size(mesaCtx, mesaDraw);
863	if (mesaRead != mesaDraw)
864	    swrast_check_and_update_window_size(mesaCtx, mesaRead);
865
866	_mesa_make_current( mesaCtx,
867			    mesaDraw,
868			    mesaRead );
869    }
870    else {
871	/* unbind */
872	_mesa_make_current( NULL, NULL, NULL );
873    }
874
875    return GL_TRUE;
876}
877
878static GLboolean
879dri_unbind_context(__DRIcontext * cPriv)
880{
881    TRACE;
882    (void) cPriv;
883
884    /* Unset current context and dispath table */
885    _mesa_make_current(NULL, NULL, NULL);
886
887    return GL_TRUE;
888}
889
890static void
891dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
892                    int w, int h)
893{
894    __DRIscreen *sPriv = dPriv->driScreenPriv;
895    void *data;
896    int iy;
897    struct dri_drawable *drawable = dri_drawable(dPriv);
898    struct gl_framebuffer *fb;
899    struct dri_swrast_renderbuffer *frontrb, *backrb;
900
901    TRACE;
902
903    fb = &drawable->Base;
904
905    frontrb =
906	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
907    backrb =
908	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
909
910    /* check for signle-buffered */
911    if (backrb == NULL)
912       return;
913
914    iy = frontrb->Base.Base.Height - y - h;
915    data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8));
916    sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
917                                    x, iy, w, h,
918                                    frontrb->pitch,
919                                    data,
920                                    dPriv->loaderPrivate);
921}
922
923
924static const struct __DriverAPIRec swrast_driver_api = {
925    .InitScreen = dri_init_screen,
926    .DestroyScreen = dri_destroy_screen,
927    .CreateContext = dri_create_context,
928    .DestroyContext = dri_destroy_context,
929    .CreateBuffer = dri_create_buffer,
930    .DestroyBuffer = dri_destroy_buffer,
931    .SwapBuffers = dri_swap_buffers,
932    .MakeCurrent = dri_make_current,
933    .UnbindContext = dri_unbind_context,
934    .CopySubBuffer = dri_copy_sub_buffer,
935};
936
937static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
938   .base = { __DRI_DRIVER_VTABLE, 1 },
939   .vtable = &swrast_driver_api,
940};
941
942static const __DRIextension *swrast_driver_extensions[] = {
943    &driCoreExtension.base,
944    &driSWRastExtension.base,
945    &driCopySubBufferExtension.base,
946    &swrast_vtable.base,
947    NULL
948};
949
950PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void)
951{
952   globalDriverAPI = &swrast_driver_api;
953
954   return swrast_driver_extensions;
955}
956