nouveau: Split nouveau_buffers into nouveau_mem and nouveau_fbo
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_fbo.c
1 #include "utils.h"
2 #include "framebuffer.h"
3 #include "renderbuffer.h"
4 #include "fbobject.h"
5
6 #include "nouveau_context.h"
7 #include "nouveau_fbo.h"
8 #include "nouveau_fifo.h"
9 #include "nouveau_msg.h"
10 #include "nouveau_object.h"
11 #include "nouveau_reg.h"
12
13 static GLboolean
14 nouveau_renderbuffer_pixelformat(nouveau_renderbuffer * nrb,
15 GLenum internalFormat)
16 {
17 nrb->mesa.InternalFormat = internalFormat;
18
19 /*TODO: We probably want to extend this a bit, and maybe make
20 * card-specific?
21 */
22 switch (internalFormat) {
23 case GL_RGBA:
24 case GL_RGBA8:
25 nrb->mesa._BaseFormat = GL_RGBA;
26 nrb->mesa._ActualFormat = GL_RGBA8;
27 nrb->mesa.DataType = GL_UNSIGNED_BYTE;
28 nrb->mesa.RedBits = 8;
29 nrb->mesa.GreenBits = 8;
30 nrb->mesa.BlueBits = 8;
31 nrb->mesa.AlphaBits = 8;
32 nrb->cpp = 4;
33 break;
34 case GL_RGB:
35 case GL_RGB5:
36 nrb->mesa._BaseFormat = GL_RGB;
37 nrb->mesa._ActualFormat = GL_RGB5;
38 nrb->mesa.DataType = GL_UNSIGNED_BYTE;
39 nrb->mesa.RedBits = 5;
40 nrb->mesa.GreenBits = 6;
41 nrb->mesa.BlueBits = 5;
42 nrb->mesa.AlphaBits = 0;
43 nrb->cpp = 2;
44 break;
45 case GL_DEPTH_COMPONENT16:
46 nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
47 nrb->mesa._ActualFormat = GL_DEPTH_COMPONENT16;
48 nrb->mesa.DataType = GL_UNSIGNED_SHORT;
49 nrb->mesa.DepthBits = 16;
50 nrb->cpp = 2;
51 break;
52 case GL_DEPTH_COMPONENT24:
53 nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
54 nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
55 nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
56 nrb->mesa.DepthBits = 24;
57 nrb->cpp = 4;
58 break;
59 case GL_STENCIL_INDEX8_EXT:
60 nrb->mesa._BaseFormat = GL_STENCIL_INDEX;
61 nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
62 nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
63 nrb->mesa.StencilBits = 8;
64 nrb->cpp = 4;
65 break;
66 case GL_DEPTH24_STENCIL8_EXT:
67 nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT;
68 nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
69 nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
70 nrb->mesa.DepthBits = 24;
71 nrb->mesa.StencilBits = 8;
72 nrb->cpp = 4;
73 break;
74 default:
75 return GL_FALSE;
76 break;
77 }
78
79 return GL_TRUE;
80 }
81
82 static GLboolean
83 nouveau_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
84 GLenum internalFormat,
85 GLuint width, GLuint height)
86 {
87 nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb;
88
89 if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) {
90 fprintf(stderr, "%s: unknown internalFormat\n", __func__);
91 return GL_FALSE;
92 }
93
94 /* If this buffer isn't statically alloc'd, we may need to ask the
95 * drm for more memory */
96 if (!nrb->dPriv && (rb->Width != width || rb->Height != height)) {
97 GLuint pitch;
98
99 /* align pitches to 64 bytes */
100 pitch = ((width * nrb->cpp) + 63) & ~63;
101
102 if (nrb->mem)
103 nouveau_mem_free(ctx, nrb->mem);
104 nrb->mem = nouveau_mem_alloc(ctx,
105 NOUVEAU_MEM_FB |
106 NOUVEAU_MEM_MAPPED,
107 pitch * height, 0);
108 if (!nrb->mem)
109 return GL_FALSE;
110
111 /* update nouveau_renderbuffer info */
112 nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem);
113 nrb->pitch = pitch;
114 }
115
116 rb->Width = width;
117 rb->Height = height;
118 rb->InternalFormat = internalFormat;
119 return GL_TRUE;
120 }
121
122 static void nouveau_renderbuffer_delete(struct gl_renderbuffer *rb)
123 {
124 GET_CURRENT_CONTEXT(ctx);
125 nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb;
126
127 if (nrb->mem)
128 nouveau_mem_free(ctx, nrb->mem);
129 FREE(nrb);
130 }
131
132 nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat,
133 GLvoid * map, GLuint offset,
134 GLuint pitch,
135 __DRIdrawablePrivate *
136 dPriv)
137 {
138 nouveau_renderbuffer *nrb;
139
140 nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
141 if (nrb) {
142 _mesa_init_renderbuffer(&nrb->mesa, 0);
143
144 nouveau_renderbuffer_pixelformat(nrb, internalFormat);
145
146 nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
147 nrb->mesa.Delete = nouveau_renderbuffer_delete;
148
149 nrb->dPriv = dPriv;
150 nrb->offset = offset;
151 nrb->pitch = pitch;
152 nrb->map = map;
153 }
154
155 return nrb;
156 }
157
158 static void
159 nouveau_cliprects_drawable_set(nouveauContextPtr nmesa,
160 nouveau_renderbuffer * nrb)
161 {
162 __DRIdrawablePrivate *dPriv = nrb->dPriv;
163
164 nmesa->numClipRects = dPriv->numClipRects;
165 nmesa->pClipRects = dPriv->pClipRects;
166 nmesa->drawX = dPriv->x;
167 nmesa->drawY = dPriv->y;
168 nmesa->drawW = dPriv->w;
169 nmesa->drawH = dPriv->h;
170 }
171
172 static void
173 nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa,
174 nouveau_renderbuffer * nrb)
175 {
176 nmesa->numClipRects = 1;
177 nmesa->pClipRects = &nmesa->osClipRect;
178 nmesa->osClipRect.x1 = 0;
179 nmesa->osClipRect.y1 = 0;
180 nmesa->osClipRect.x2 = nrb->mesa.Width;
181 nmesa->osClipRect.y2 = nrb->mesa.Height;
182 nmesa->drawX = 0;
183 nmesa->drawY = 0;
184 nmesa->drawW = nrb->mesa.Width;
185 nmesa->drawH = nrb->mesa.Height;
186 }
187
188 void nouveau_window_moved(GLcontext * ctx)
189 {
190 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
191 nouveau_renderbuffer *nrb;
192
193 nrb = (nouveau_renderbuffer *)ctx->DrawBuffer->_ColorDrawBuffers[0][0];
194 if (!nrb)
195 return;
196
197 if (!nrb->dPriv)
198 nouveau_cliprects_renderbuffer_set(nmesa, nrb);
199 else
200 nouveau_cliprects_drawable_set(nmesa, nrb);
201
202 /* Viewport depends on window size/position, nouveauCalcViewport
203 * will take care of calling the hw-specific WindowMoved
204 */
205 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
206 ctx->Viewport.Width, ctx->Viewport.Height);
207 /* Scissor depends on window position */
208 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
209 ctx->Scissor.Width, ctx->Scissor.Height);
210 }
211
212 GLboolean
213 nouveau_build_framebuffer(GLcontext * ctx, struct gl_framebuffer *fb)
214 {
215 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
216 nouveau_renderbuffer *color[MAX_DRAW_BUFFERS];
217 nouveau_renderbuffer *depth;
218
219 _mesa_update_framebuffer(ctx);
220 _mesa_update_draw_buffer_bounds(ctx);
221
222 color[0] = (nouveau_renderbuffer *) fb->_ColorDrawBuffers[0][0];
223 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped)
224 depth = (nouveau_renderbuffer *) fb->_DepthBuffer->Wrapped;
225 else
226 depth = (nouveau_renderbuffer *) fb->_DepthBuffer;
227
228 if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth))
229 return GL_FALSE;
230 nouveau_window_moved(ctx);
231
232 return GL_TRUE;
233 }
234
235 static void nouveauDrawBuffer(GLcontext * ctx, GLenum buffer)
236 {
237 nouveau_build_framebuffer(ctx, ctx->DrawBuffer);
238 }
239
240 static struct gl_framebuffer *nouveauNewFramebuffer(GLcontext * ctx,
241 GLuint name)
242 {
243 return _mesa_new_framebuffer(ctx, name);
244 }
245
246 static struct gl_renderbuffer *nouveauNewRenderbuffer(GLcontext * ctx,
247 GLuint name)
248 {
249 nouveau_renderbuffer *nrb;
250
251 nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
252 if (nrb) {
253 _mesa_init_renderbuffer(&nrb->mesa, name);
254
255 nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
256 nrb->mesa.Delete = nouveau_renderbuffer_delete;
257 }
258 return &nrb->mesa;
259 }
260
261 static void
262 nouveauBindFramebuffer(GLcontext * ctx, GLenum target,
263 struct gl_framebuffer *fb,
264 struct gl_framebuffer *fbread)
265 {
266 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
267 nouveau_build_framebuffer(ctx, fb);
268 }
269 }
270
271 static void
272 nouveauFramebufferRenderbuffer(GLcontext * ctx,
273 struct gl_framebuffer *fb,
274 GLenum attachment,
275 struct gl_renderbuffer *rb)
276 {
277 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
278 nouveau_build_framebuffer(ctx, fb);
279 }
280
281 static void
282 nouveauRenderTexture(GLcontext * ctx,
283 struct gl_framebuffer *fb,
284 struct gl_renderbuffer_attachment *att)
285 {
286 }
287
288 static void
289 nouveauFinishRenderTexture(GLcontext * ctx,
290 struct gl_renderbuffer_attachment *att)
291 {
292 }
293
294 void nouveauInitBufferFuncs(struct dd_function_table *func)
295 {
296 func->DrawBuffer = nouveauDrawBuffer;
297
298 func->NewFramebuffer = nouveauNewFramebuffer;
299 func->NewRenderbuffer = nouveauNewRenderbuffer;
300 func->BindFramebuffer = nouveauBindFramebuffer;
301 func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer;
302 func->RenderTexture = nouveauRenderTexture;
303 func->FinishRenderTexture = nouveauFinishRenderTexture;
304 }