• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 **
nouveau_get_configs(void)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 **
nouveau_init_screen2(__DRIscreen * dri_screen)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
nouveau_destroy_screen(__DRIscreen * dri_screen)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
nouveau_create_buffer(__DRIscreen * dri_screen,__DRIdrawable * drawable,const struct gl_config * visual,GLboolean is_pixmap)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
nouveau_destroy_buffer(__DRIdrawable * drawable)211 nouveau_destroy_buffer(__DRIdrawable *drawable)
212 {
213 	_mesa_reference_framebuffer(
214 		(struct gl_framebuffer **)&drawable->driverPrivate, NULL);
215 }
216 
217 static void
nouveau_drawable_flush(__DRIdrawable * draw)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