Home | History | Annotate | Download | only in nouveau
      1 /*
      2  * Copyright (C) 2009 Francisco Jerez.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial
     15  * portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  */
     26 
     27 #include "nouveau_driver.h"
     28 #include "nouveau_context.h"
     29 #include "nouveau_fbo.h"
     30 #include "nouveau_texture.h"
     31 #include "nv04_driver.h"
     32 #include "nv10_driver.h"
     33 #include "nv20_driver.h"
     34 
     35 #include "main/framebuffer.h"
     36 #include "main/fbobject.h"
     37 #include "main/renderbuffer.h"
     38 #include "swrast/s_renderbuffer.h"
     39 
     40 static const __DRIextension *nouveau_screen_extensions[];
     41 
     42 static void
     43 nouveau_destroy_screen(__DRIscreen *dri_screen);
     44 
     45 static const __DRIconfig **
     46 nouveau_get_configs(void)
     47 {
     48 	__DRIconfig **configs = NULL;
     49 	int i;
     50 
     51 	const uint8_t depth_bits[]   = { 0, 16, 24, 24 };
     52 	const uint8_t stencil_bits[] = { 0,  0,  0,  8 };
     53 	const uint8_t msaa_samples[] = { 0 };
     54 
     55 	const struct {
     56 		GLenum format;
     57 		GLenum type;
     58 	} fb_formats[] = {
     59 		{ GL_RGB , GL_UNSIGNED_SHORT_5_6_5     },
     60 		{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
     61 		{ GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
     62 	};
     63 
     64 	const GLenum back_buffer_modes[] = {
     65 		GLX_NONE, GLX_SWAP_UNDEFINED_OML
     66 	};
     67 
     68 	for (i = 0; i < Elements(fb_formats); i++) {
     69 		__DRIconfig **config;
     70 
     71 		config = driCreateConfigs(fb_formats[i].format,
     72 					  fb_formats[i].type,
     73 					  depth_bits, stencil_bits,
     74 					  Elements(depth_bits),
     75 					  back_buffer_modes,
     76 					  Elements(back_buffer_modes),
     77 					  msaa_samples,
     78 					  Elements(msaa_samples),
     79 					  GL_TRUE);
     80 		assert(config);
     81 
     82 		configs = driConcatConfigs(configs, config);
     83 	}
     84 
     85 	return (const __DRIconfig **)configs;
     86 }
     87 
     88 static const __DRIconfig **
     89 nouveau_init_screen2(__DRIscreen *dri_screen)
     90 {
     91 	const __DRIconfig **configs;
     92 	struct nouveau_screen *screen;
     93 	int ret;
     94 
     95 	/* Allocate the screen. */
     96 	screen = CALLOC_STRUCT(nouveau_screen);
     97 	if (!screen)
     98 		return NULL;
     99 
    100 	dri_screen->driverPrivate = screen;
    101 	dri_screen->extensions = nouveau_screen_extensions;
    102 	screen->dri_screen = dri_screen;
    103 
    104 	/* Open the DRM device. */
    105 	ret = nouveau_device_wrap(dri_screen->fd, 0, &screen->device);
    106 	if (ret) {
    107 		nouveau_error("Error opening the DRM device.\n");
    108 		goto fail;
    109 	}
    110 
    111 	/* Choose the card specific function pointers. */
    112 	switch (screen->device->chipset & 0xf0) {
    113 	case 0x00:
    114 		screen->driver = &nv04_driver;
    115 		break;
    116 	case 0x10:
    117 		screen->driver = &nv10_driver;
    118 		break;
    119 	case 0x20:
    120 		screen->driver = &nv20_driver;
    121 		break;
    122 	default:
    123 		assert(0);
    124 	}
    125 
    126 	configs = nouveau_get_configs();
    127 	if (!configs)
    128 		goto fail;
    129 
    130 	return configs;
    131 fail:
    132 	nouveau_destroy_screen(dri_screen);
    133 	return NULL;
    134 
    135 }
    136 
    137 static void
    138 nouveau_destroy_screen(__DRIscreen *dri_screen)
    139 {
    140 	struct nouveau_screen *screen = dri_screen->driverPrivate;
    141 
    142 	if (!screen)
    143 		return;
    144 
    145 	nouveau_device_del(&screen->device);
    146 
    147 	FREE(screen);
    148 	dri_screen->driverPrivate = NULL;
    149 }
    150 
    151 static GLboolean
    152 nouveau_create_buffer(__DRIscreen *dri_screen,
    153 		      __DRIdrawable *drawable,
    154 		      const struct gl_config *visual,
    155 		      GLboolean is_pixmap)
    156 {
    157 	struct gl_renderbuffer *rb;
    158 	struct gl_framebuffer *fb;
    159 	GLenum color_format;
    160 
    161 	if (is_pixmap)
    162 		return GL_FALSE; /* not implemented */
    163 
    164 	if (visual->redBits == 5)
    165 		color_format = GL_RGB5;
    166 	else if (visual->alphaBits == 0)
    167 		color_format = GL_RGB8;
    168 	else
    169 		color_format = GL_RGBA8;
    170 
    171 	fb = nouveau_framebuffer_dri_new(visual);
    172 	if (!fb)
    173 		return GL_FALSE;
    174 
    175 	/* Front buffer. */
    176 	rb = nouveau_renderbuffer_dri_new(color_format, drawable);
    177 	_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb);
    178 
    179 	/* Back buffer */
    180 	if (visual->doubleBufferMode) {
    181 		rb = nouveau_renderbuffer_dri_new(color_format, drawable);
    182 		_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb);
    183 	}
    184 
    185 	/* Depth/stencil buffer. */
    186 	if (visual->depthBits == 24 && visual->stencilBits == 8) {
    187 		rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
    188 		_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
    189 		_mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
    190 
    191 	} else if (visual->depthBits == 24) {
    192 		rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
    193 		_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
    194 
    195 	} else if (visual->depthBits == 16) {
    196 		rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
    197 		_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
    198 	}
    199 
    200 	/* Software renderbuffers. */
    201 	_swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
    202                                        visual->accumRedBits > 0,
    203                                        GL_FALSE, GL_FALSE);
    204 
    205 	drawable->driverPrivate = fb;
    206 
    207 	return GL_TRUE;
    208 }
    209 
    210 static void
    211 nouveau_destroy_buffer(__DRIdrawable *drawable)
    212 {
    213 	_mesa_reference_framebuffer(
    214 		(struct gl_framebuffer **)&drawable->driverPrivate, NULL);
    215 }
    216 
    217 static void
    218 nouveau_drawable_flush(__DRIdrawable *draw)
    219 {
    220 }
    221 
    222 static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
    223     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
    224     nouveau_drawable_flush,
    225     dri2InvalidateDrawable,
    226 };
    227 
    228 static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
    229     { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
    230     NULL,
    231     nouveau_set_texbuffer,
    232 };
    233 
    234 static const __DRIextension *nouveau_screen_extensions[] = {
    235     &nouveau_flush_extension.base,
    236     &nouveau_texbuffer_extension.base,
    237     &dri2ConfigQueryExtension.base,
    238     NULL
    239 };
    240 
    241 const struct __DriverAPIRec driDriverAPI = {
    242 	.InitScreen      = nouveau_init_screen2,
    243 	.DestroyScreen   = nouveau_destroy_screen,
    244 	.CreateBuffer    = nouveau_create_buffer,
    245 	.DestroyBuffer   = nouveau_destroy_buffer,
    246 	.CreateContext   = nouveau_context_create,
    247 	.DestroyContext  = nouveau_context_destroy,
    248 	.MakeCurrent     = nouveau_context_make_current,
    249 	.UnbindContext   = nouveau_context_unbind,
    250 };
    251 
    252 /* This is the table of extensions that the loader will dlsym() for. */
    253 PUBLIC const __DRIextension *__driDriverExtensions[] = {
    254 	&driCoreExtension.base,
    255 	&driDRI2Extension.base,
    256 	NULL
    257 };
    258