1 /*
2 * Copyright 2006 Joseph Garvin
3 * Copyright 2012 Connor Behan
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 "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Joseph Garvin <joseph.h.garvin@gmail.com>
27 * Connor Behan <connor.behan@gmail.com>
28 *
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "r128.h"
36 #include "exa.h"
37
38 #include "r128_reg.h"
39 #include "r128_rop.h"
40
41 #include "xf86.h"
42
43 /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
44 * require src and dest datatypes to be equal.
45 */
R128GetDatatypeBpp(int bpp,uint32_t * type)46 Bool R128GetDatatypeBpp(int bpp, uint32_t *type)
47 {
48 switch (bpp) {
49 case 8:
50 *type = R128_DATATYPE_CI8;
51 return TRUE;
52 case 16:
53 *type = R128_DATATYPE_RGB565;
54 return TRUE;
55 case 24:
56 *type = R128_DATATYPE_RGB888;
57 return TRUE;
58 case 32:
59 *type = R128_DATATYPE_ARGB8888;
60 return TRUE;
61 default:
62 return FALSE;
63 }
64 }
65
R128GetOffsetPitch(PixmapPtr pPix,int bpp,uint32_t * pitch_offset,unsigned int offset,unsigned int pitch)66 static Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
67 unsigned int offset, unsigned int pitch)
68 {
69 ScreenPtr pScreen = pPix->drawable.pScreen;
70 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
71 R128InfoPtr info = R128PTR(pScrn);
72
73 if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) {
74 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
75 "Bad pitch 0x%08x\n", pitch));
76 return FALSE;
77 }
78
79 if (offset % info->ExaDriver->pixmapOffsetAlign != 0) {
80 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
81 "Bad offset 0x%08x\n", offset));
82 return FALSE;
83 }
84
85 *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
86
87 return TRUE;
88 }
89
R128GetPixmapOffsetPitch(PixmapPtr pPix,uint32_t * pitch_offset)90 Bool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
91 {
92 uint32_t pitch, offset;
93 int bpp;
94
95 bpp = pPix->drawable.bitsPerPixel;
96 if (bpp == 24)
97 bpp = 8;
98
99 offset = exaGetPixmapOffset(pPix);
100 pitch = exaGetPixmapPitch(pPix);
101
102 return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
103 }
104
Emit2DState(ScrnInfoPtr pScrn)105 static void Emit2DState(ScrnInfoPtr pScrn)
106 {
107 R128InfoPtr info = R128PTR(pScrn);
108 int has_src = info->state_2d.src_pitch_offset;
109 unsigned char *R128MMIO = info->MMIO;
110
111 R128WaitForFifo(pScrn, (has_src ? 10 : 9));
112
113 OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
114 OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
115 OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
116 OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
117 OUTREG(R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr);
118 OUTREG(R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr);
119 OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask);
120 OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl);
121
122 OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
123 if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
124 }
125
126 #ifdef R128DRI
EmitCCE2DState(ScrnInfoPtr pScrn)127 void EmitCCE2DState(ScrnInfoPtr pScrn)
128 {
129 R128InfoPtr info = R128PTR(pScrn);
130 int has_src = info->state_2d.src_pitch_offset;
131 RING_LOCALS;
132
133 R128CCE_REFRESH( pScrn, info );
134
135 BEGIN_RING( (has_src ? 20 : 18) );
136
137 OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right );
138 OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl );
139 OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr );
140 OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr );
141 OUT_RING_REG( R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr );
142 OUT_RING_REG( R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr );
143 OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask );
144 OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl );
145
146 OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset );
147 if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset );
148
149 ADVANCE_RING();
150 }
151 #endif
152
153 /* EXA Callbacks */
154
155 static Bool
R128PrepareSolid(PixmapPtr pPixmap,int alu,Pixel planemask,Pixel fg)156 R128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
157 {
158 ScreenPtr pScreen = pPixmap->drawable.pScreen;
159 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
160 R128InfoPtr info = R128PTR(pScrn);
161
162 int bpp = pPixmap->drawable.bitsPerPixel;
163 uint32_t datatype, dst_pitch_offset;
164
165 if (!R128GetDatatypeBpp(bpp, &datatype)) {
166 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
167 "R128GetDatatypeBpp failed\n"));
168 return FALSE;
169 }
170 if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) {
171 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
172 "R128GetPixmapOffsetPitch failed\n"));
173 return FALSE;
174 }
175 if (info->state_2d.in_use) return FALSE;
176
177 info->state_2d.in_use = TRUE;
178 info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
179 info->state_2d.dp_brush_bkgd_clr = 0x00000000;
180 info->state_2d.dp_src_frgd_clr = 0xffffffff;
181 info->state_2d.dp_src_bkgd_clr = 0x00000000;
182 info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
183 R128_GMC_BRUSH_SOLID_COLOR |
184 (datatype >> 8) |
185 R128_GMC_SRC_DATATYPE_COLOR |
186 R128_ROP[alu].pattern |
187 R128_GMC_CLR_CMP_CNTL_DIS);
188 info->state_2d.dp_brush_frgd_clr = fg;
189 info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
190 info->state_2d.dp_write_mask = planemask;
191 info->state_2d.dst_pitch_offset = dst_pitch_offset;
192 info->state_2d.src_pitch_offset = 0;
193
194 #ifdef R128DRI
195 if (info->directRenderingEnabled) {
196 EmitCCE2DState(pScrn);
197 } else
198 #endif
199 {
200 Emit2DState(pScrn);
201 }
202 return TRUE;
203 }
204
205 static void
R128Solid(PixmapPtr pPixmap,int x1,int y1,int x2,int y2)206 R128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
207 {
208 ScreenPtr pScreen = pPixmap->drawable.pScreen;
209 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
210 R128InfoPtr info = R128PTR(pScrn);
211 unsigned char *R128MMIO = info->MMIO;
212
213 R128WaitForFifo(pScrn, 2);
214 OUTREG(R128_DST_Y_X, (y1 << 16) | x1);
215 OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1));
216 }
217
218 #define R128DoneSolid R128Done
219
220 void
R128DoPrepareCopy(ScrnInfoPtr pScrn,uint32_t src_pitch_offset,uint32_t dst_pitch_offset,uint32_t datatype,int alu,Pixel planemask)221 R128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
222 uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask)
223 {
224 R128InfoPtr info = R128PTR(pScrn);
225
226 info->state_2d.in_use = TRUE;
227 info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
228 R128_GMC_SRC_PITCH_OFFSET_CNTL |
229 R128_GMC_BRUSH_NONE |
230 (datatype >> 8) |
231 R128_GMC_SRC_DATATYPE_COLOR |
232 R128_ROP[alu].rop |
233 R128_DP_SRC_SOURCE_MEMORY |
234 R128_GMC_CLR_CMP_CNTL_DIS);
235 info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
236 (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0));
237 info->state_2d.dp_brush_frgd_clr = 0xffffffff;
238 info->state_2d.dp_brush_bkgd_clr = 0x00000000;
239 info->state_2d.dp_src_frgd_clr = 0xffffffff;
240 info->state_2d.dp_src_bkgd_clr = 0x00000000;
241 info->state_2d.dp_write_mask = planemask;
242 info->state_2d.dst_pitch_offset = dst_pitch_offset;
243 info->state_2d.src_pitch_offset = src_pitch_offset;
244 info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
245
246 #ifdef R128DRI
247 if (info->directRenderingEnabled) {
248 EmitCCE2DState(pScrn);
249 } else
250 #endif
251 {
252 Emit2DState(pScrn);
253 }
254 }
255
256 static Bool
R128PrepareCopy(PixmapPtr pSrcPixmap,PixmapPtr pDstPixmap,int xdir,int ydir,int alu,Pixel planemask)257 R128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask)
258 {
259 ScreenPtr pScreen = pSrcPixmap->drawable.pScreen;
260 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
261 R128InfoPtr info = R128PTR(pScrn);
262
263 int bpp = pDstPixmap->drawable.bitsPerPixel;
264 uint32_t datatype, src_pitch_offset, dst_pitch_offset;
265
266 if (!R128GetDatatypeBpp(bpp, &datatype)) {
267 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
268 "R128GetDatatypeBpp failed\n"));
269 return FALSE;
270 }
271 if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) {
272 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
273 "R128GetPixmapOffsetPitch source "
274 "failed\n"));
275 return FALSE;
276 }
277 if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) {
278 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
279 "R128GetPixmapOffsetPitch dest failed\n"));
280 return FALSE;
281 }
282 if (info->state_2d.in_use) return FALSE;
283
284 info->xdir = xdir;
285 info->ydir = ydir;
286
287 R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask);
288
289 return TRUE;
290 }
291
292 static void
R128Copy(PixmapPtr pDstPixmap,int srcX,int srcY,int dstX,int dstY,int width,int height)293 R128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
294 {
295 ScreenPtr pScreen = pDstPixmap->drawable.pScreen;
296 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
297 R128InfoPtr info = R128PTR(pScrn);
298 unsigned char *R128MMIO = info->MMIO;
299
300 if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
301 if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
302
303 R128WaitForFifo(pScrn, 3);
304 OUTREG(R128_SRC_Y_X, (srcY << 16) | srcX);
305 OUTREG(R128_DST_Y_X, (dstY << 16) | dstX);
306 OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width);
307 }
308
309 #define R128DoneCopy R128Done
310
311 static void
R128Sync(ScreenPtr pScreen,int marker)312 R128Sync(ScreenPtr pScreen, int marker)
313 {
314 R128WaitForIdle(xf86ScreenToScrn(pScreen));
315 }
316
317 void
R128Done(PixmapPtr pPixmap)318 R128Done(PixmapPtr pPixmap)
319 {
320 ScreenPtr pScreen = pPixmap->drawable.pScreen;
321 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
322 R128InfoPtr info = R128PTR(pScrn);
323
324 info->state_2d.in_use = FALSE;
325 #if defined(R128DRI) && defined(RENDER)
326 if (info->state_2d.src_pix) {
327 pScreen->DestroyPixmap(info->state_2d.src_pix);
328 info->state_2d.src_pix = NULL;
329 }
330 if (info->state_2d.msk_pix) {
331 pScreen->DestroyPixmap(info->state_2d.msk_pix);
332 info->state_2d.msk_pix = NULL;
333 }
334 #endif
335 }
336
337 #ifdef R128DRI
338
339 #define R128CCEPrepareSolid R128PrepareSolid
340
341 static void
R128CCESolid(PixmapPtr pPixmap,int x1,int y1,int x2,int y2)342 R128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
343 {
344 ScreenPtr pScreen = pPixmap->drawable.pScreen;
345 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
346 R128InfoPtr info = R128PTR(pScrn);
347 RING_LOCALS;
348
349 R128CCE_REFRESH( pScrn, info );
350
351 BEGIN_RING( 4 );
352
353 OUT_RING_REG( R128_DST_Y_X, (y1 << 16) | x1 );
354 OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) );
355
356 ADVANCE_RING();
357 }
358
359 #define R128CCEDoneSolid R128Done
360
361 #define R128CCEPrepareCopy R128PrepareCopy
362
363 static void
R128CCECopy(PixmapPtr pDstPixmap,int srcX,int srcY,int dstX,int dstY,int width,int height)364 R128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
365 int width, int height)
366 {
367 ScreenPtr pScreen = pDstPixmap->drawable.pScreen;
368 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
369 R128InfoPtr info = R128PTR(pScrn);
370 RING_LOCALS;
371
372 R128CCE_REFRESH( pScrn, info );
373
374 if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
375 if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
376
377 BEGIN_RING( 6 );
378
379 OUT_RING_REG( R128_SRC_Y_X, (srcY << 16) | srcX );
380 OUT_RING_REG( R128_DST_Y_X, (dstY << 16) | dstX );
381 OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width );
382
383 ADVANCE_RING();
384 }
385
386 #define R128CCEDoneCopy R128Done
387
388 static void
R128CCESync(ScreenPtr pScreen,int marker)389 R128CCESync(ScreenPtr pScreen, int marker)
390 {
391 R128CCEWaitForIdle(xf86ScreenToScrn(pScreen));
392 }
393
394 #endif
395
396 Bool
R128EXAInit(ScreenPtr pScreen,int total)397 R128EXAInit(ScreenPtr pScreen, int total)
398 {
399 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
400 R128InfoPtr info = R128PTR(pScrn);
401
402 info->ExaDriver = exaDriverAlloc();
403 if (!info->ExaDriver) {
404 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
405 "Could not allocate EXA driver...\n");
406 return FALSE;
407 }
408
409 info->ExaDriver->exa_major = EXA_VERSION_MAJOR;
410 info->ExaDriver->exa_minor = EXA_VERSION_MINOR;
411
412 info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset;
413 info->ExaDriver->offScreenBase = pScrn->virtualY *
414 (pScrn->displayWidth *
415 info->CurrentLayout.pixel_bytes);
416 info->ExaDriver->memorySize = total;
417 info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT;
418
419 #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
420 info->ExaDriver->maxPitchBytes = 16320;
421 #endif
422 /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */
423 info->ExaDriver->pixmapPitchAlign = 32;
424 info->ExaDriver->pixmapOffsetAlign = 32;
425 info->ExaDriver->maxX = 2048;
426 info->ExaDriver->maxY = 2048;
427
428 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
429 "Setting up EXA callbacks\n");
430
431 #ifdef R128DRI
432 if (info->directRenderingEnabled) {
433 info->ExaDriver->PrepareSolid = R128CCEPrepareSolid;
434 info->ExaDriver->Solid = R128CCESolid;
435 info->ExaDriver->DoneSolid = R128CCEDoneSolid;
436
437 info->ExaDriver->PrepareCopy = R128CCEPrepareCopy;
438 info->ExaDriver->Copy = R128CCECopy;
439 info->ExaDriver->DoneCopy = R128CCEDoneCopy;
440
441 #ifdef RENDER
442 if (info->RenderAccel) {
443 info->ExaDriver->CheckComposite = R128CCECheckComposite;
444 info->ExaDriver->PrepareComposite = R128CCEPrepareComposite;
445 info->ExaDriver->Composite = R128CCEComposite;
446 info->ExaDriver->DoneComposite = R128CCEDoneComposite;
447 }
448 #endif
449
450 info->ExaDriver->WaitMarker = R128CCESync;
451 } else
452 #endif
453 {
454 info->ExaDriver->PrepareSolid = R128PrepareSolid;
455 info->ExaDriver->Solid = R128Solid;
456 info->ExaDriver->DoneSolid = R128DoneSolid;
457
458 info->ExaDriver->PrepareCopy = R128PrepareCopy;
459 info->ExaDriver->Copy = R128Copy;
460 info->ExaDriver->DoneCopy = R128DoneCopy;
461
462 /* The registers used for r128 compositing are CCE specific, just like the
463 * registers used for radeon compositing are CP specific. The radeon driver
464 * falls back to different registers when there is no DRI. The equivalent
465 * registers on the r128 (if they even exist) are not listed in the register
466 * file so I can't implement compositing without DRI.
467 */
468
469 info->ExaDriver->WaitMarker = R128Sync;
470 }
471
472 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
473 "Initializing 2D acceleration engine...\n");
474
475 R128EngineInit(pScrn);
476
477 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
478 "Initializing EXA driver...\n");
479
480 if (!exaDriverInit(pScreen, info->ExaDriver)) {
481 free(info->ExaDriver);
482 return FALSE;
483 }
484
485 info->state_2d.composite_setup = FALSE;
486 return TRUE;
487 }
488