cg6_accel.c revision 7fd8a0c2
11.1Sjtc/*
21.1Sjtc * Sun GX and Turbo GX acceleration support
31.1Sjtc *
41.1Sjtc * Copyright (C) 2005 Michael Lorenz
51.1Sjtc *
61.1Sjtc * Permission is hereby granted, free of charge, to any person obtaining a copy
71.1Sjtc * of this software and associated documentation files (the "Software"), to deal
81.1Sjtc * in the Software without restriction, including without limitation the rights
91.1Sjtc * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101.1Sjtc * copies of the Software, and to permit persons to whom the Software is
111.1Sjtc * furnished to do so, subject to the following conditions:
121.1Sjtc *
131.1Sjtc * The above copyright notice and this permission notice shall be included in
141.1Sjtc * all copies or substantial portions of the Software.
151.1Sjtc *
161.1Sjtc * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171.1Sjtc * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181.1Sjtc * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
191.1Sjtc * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
201.1Sjtc * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
211.1Sjtc * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
221.1Sjtc */
231.1Sjtc/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/suncg6/cg6_accel.c $ */
241.1Sjtc
251.1Sjtc#include "cg6.h"
261.1Sjtc#include "cg6_regs.h"
271.1Sjtc#include "dgaproc.h"
281.1Sjtc
291.1Sjtc
301.1Sjtcstatic CARD32 Cg6BlitROP[] = {
311.1Sjtc    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
321.1Sjtc    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
331.1Sjtc    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
341.1Sjtc    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
351.1Sjtc    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
361.1Sjtc    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
371.1Sjtc    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
381.1Sjtc    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
391.1Sjtc    ROP_BLIT(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
401.1Sjtc    ROP_BLIT(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
411.1Sjtc    ROP_BLIT(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
421.1Sjtc    ROP_BLIT(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
431.1Sjtc    ROP_BLIT(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
441.1Sjtc    ROP_BLIT(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
451.1Sjtc    ROP_BLIT(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
461.1Sjtc    ROP_BLIT(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
471.1Sjtc};
481.1Sjtc
491.1Sjtcstatic CARD32 Cg6DrawROP[] = {
501.1Sjtc    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
511.1Sjtc    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
521.1Sjtc    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
531.1Sjtc    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
541.1Sjtc    ROP_FILL(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
551.1Sjtc    ROP_FILL(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
561.1Sjtc    ROP_FILL(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
571.1Sjtc    ROP_FILL(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
581.1Sjtc    ROP_FILL(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
591.1Sjtc    ROP_FILL(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
601.1Sjtc    ROP_FILL(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
611.1Sjtc    ROP_FILL(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
621.1Sjtc    ROP_FILL(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
631.1Sjtc    ROP_FILL(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
641.1Sjtc    ROP_FILL(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
651.1Sjtc    ROP_FILL(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
661.1Sjtc};
671.1Sjtc
681.1Sjtcstatic CARD32 Cg6StippleROP[16]={
691.1Sjtc    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
701.1Sjtc    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
711.1Sjtc    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
721.1Sjtc    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
731.1Sjtc    ROP_STIP(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
741.1Sjtc    ROP_STIP(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
751.1Sjtc    ROP_STIP(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
761.1Sjtc    ROP_STIP(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
771.1Sjtc    ROP_STIP(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
781.1Sjtc    ROP_STIP(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
791.1Sjtc    ROP_STIP(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
801.1Sjtc    ROP_STIP(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
811.1Sjtc    ROP_STIP(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
821.1Sjtc    ROP_STIP(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
831.1Sjtc    ROP_STIP(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
841.1Sjtc    ROP_STIP(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
851.1Sjtc};
861.1Sjtc
871.1Sjtcstatic CARD32 Cg6OpaqueStippleROP[16]={
881.1Sjtc    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
891.1Sjtc    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
901.1Sjtc    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
911.1Sjtc    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
921.1Sjtc    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
931.1Sjtc    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
941.1Sjtc    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
951.1Sjtc    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
961.1Sjtc    ROP_OSTP(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
971.1Sjtc    ROP_OSTP(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
98    ROP_OSTP(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
99    ROP_OSTP(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
100    ROP_OSTP(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
101    ROP_OSTP(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
102    ROP_OSTP(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
103    ROP_OSTP(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
104};
105
106/* DGA stuff */
107
108static Bool Cg6_OpenFramebuffer(ScrnInfoPtr pScrn, char **, unsigned int *mem,
109    unsigned int *, unsigned int *, unsigned int *);
110static Bool Cg6_SetMode(ScrnInfoPtr, DGAModePtr);
111static void Cg6_SetViewport(ScrnInfoPtr, int, int, int);
112static int Cg6_GetViewport(ScrnInfoPtr);
113static void Cg6_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
114static void Cg6_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
115
116static void Cg6Sync(ScrnInfoPtr);
117
118static DGAFunctionRec Cg6_DGAFuncs = {
119	Cg6_OpenFramebuffer,
120	NULL,
121	Cg6_SetMode,
122	Cg6_SetViewport,
123	Cg6_GetViewport,
124	Cg6Sync,
125	Cg6_FillRect,
126	Cg6_BlitRect,
127	NULL
128};
129
130
131/*
132 * wait until the engine is idle
133 * unclip since clipping also influences framebuffer accesses
134 */
135static void
136Cg6Sync(ScrnInfoPtr pScrn)
137{
138    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
139
140    while (pCg6->fbc->s & GX_INPROGRESS);
141    pCg6->fbc->clipminx = 0;
142    pCg6->fbc->clipmaxx = pCg6->width;
143    pCg6->fbc->clipminy = 0;
144    pCg6->fbc->clipmaxy = pCg6->maxheight;
145}
146
147#define runDraw(pCg6) { volatile CARD32 rubbish = pCg6->fbc->draw; }
148#define runBlit(pCg6) { volatile CARD32 rubbish = pCg6->fbc->blit; }
149#define waitReady(pCg6) while(pCg6->fbc->s & GX_FULL)
150
151/*
152 * restore clipping values set by the Xserver since we're messing with them in
153 * CPU-to-screen colour expansion
154 */
155
156static void
157unClip(Cg6Ptr pCg6)
158{
159    pCg6->fbc->clipminx = pCg6->clipxa;
160    pCg6->fbc->clipmaxx = pCg6->clipxe;
161}
162
163static void
164Cg6InitEngine(Cg6Ptr pCg6)
165{
166    pCg6->clipxa = 0;
167    pCg6->clipxe = pCg6->width;
168    pCg6->fbc->clipminx = 0;
169    pCg6->fbc->clipmaxx = pCg6->width;
170    pCg6->fbc->clipminy = 0;
171    pCg6->fbc->clipmaxy = pCg6->maxheight;
172
173    pCg6->fbc->mode = GX_BLIT_SRC |
174		GX_MODE_COLOR8 |
175		GX_DRAW_RENDER |
176		GX_BWRITE0_ENABLE |
177		GX_BWRITE1_DISABLE |
178		GX_BREAD_0 |
179		GX_BDISP_0;
180
181    pCg6->fbc->fg = 0xff;
182    pCg6->fbc->bg = 0x00;
183
184    /* we ignore the pixel mask anyway but for completeness... */
185    pCg6->fbc->pixelm = ~0;
186
187    pCg6->fbc->s = 0;
188    pCg6->fbc->clip = 0;
189    pCg6->fbc->offx = 0;
190    pCg6->fbc->offy = 0;
191    pCg6->fbc->incx = 0;
192    pCg6->fbc->incy = 0;
193}
194
195static void
196Cg6SetupForScreenToScreenCopy(
197    ScrnInfoPtr  pScrn,
198    int          xdir,
199    int          ydir,
200    int          rop,
201    unsigned int planemask,
202    int          TransparencyColour
203)
204{
205    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
206
207    waitReady(pCg6);
208    unClip(pCg6);
209
210    pCg6->fbc->mode = GX_BLIT_SRC |
211		GX_MODE_COLOR8 |
212		GX_DRAW_RENDER |
213		GX_BWRITE0_ENABLE |
214		GX_BWRITE1_DISABLE |
215		GX_BREAD_0 |
216		GX_BDISP_0;
217
218    /* we probably don't need the following three */
219    pCg6->fbc->fg = 0xff;
220    pCg6->fbc->bg = 0x00;
221    pCg6->fbc->s = 0;
222
223    pCg6->fbc->alu = Cg6BlitROP[rop];
224    pCg6->fbc->pm = planemask;
225}
226
227static void
228Cg6SubsequentScreenToScreenCopy
229(
230    ScrnInfoPtr pScrn,
231    int         xSrc,
232    int         ySrc,
233    int         xDst,
234    int         yDst,
235    int         w,
236    int         h
237)
238{
239    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
240
241    waitReady(pCg6);
242    pCg6->fbc->x0 = xSrc;
243    pCg6->fbc->y0 = ySrc;
244    pCg6->fbc->x1 = xSrc + w - 1;
245    pCg6->fbc->y1 = ySrc + h - 1;
246    pCg6->fbc->x2 = xDst;
247    pCg6->fbc->y2 = yDst;
248    pCg6->fbc->x3 = xDst + w - 1;
249    pCg6->fbc->y3 = yDst + h - 1;
250    runBlit(pCg6);
251}
252
253static void
254Cg6SetupForSolidFill
255(
256    ScrnInfoPtr  pScrn,
257    int          colour,
258    int          rop,
259    unsigned int planemask
260)
261{
262    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
263    CARD32 c2;
264
265    waitReady(pCg6);
266    unClip(pCg6);
267
268    pCg6->fbc->mode = GX_BLIT_SRC |
269		GX_MODE_COLOR8 |
270		GX_DRAW_RENDER |
271		GX_BWRITE0_ENABLE |
272		GX_BWRITE1_DISABLE |
273		GX_BREAD_0 |
274		GX_BDISP_0;
275    pCg6->fbc->fg = colour;
276    pCg6->fbc->s = 0;
277    pCg6->fbc->alu = Cg6DrawROP[rop];
278    pCg6->fbc->pm = planemask;
279}
280
281static void
282Cg6SubsequentSolidFillRect
283(
284    ScrnInfoPtr pScrn,
285    int         x,
286    int         y,
287    int         w,
288    int         h
289)
290{
291    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
292
293    waitReady(pCg6);
294    pCg6->fbc->arecty = y;
295    pCg6->fbc->arectx = x;
296    /* use the relative coordinate registers - saves two additions */
297    pCg6->fbc->rrecty = h - 1;
298    pCg6->fbc->rrectx = w - 1;
299    runDraw(pCg6);
300}
301
302static void
303Cg6SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
304        		int fg, int bg,
305			int rop,
306			unsigned int planemask)
307{
308    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
309
310    waitReady(pCg6);
311    pCg6->fbc->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
312
313    if(bg == -1) {
314	/* transparent */
315	pCg6->fbc->alu = Cg6StippleROP[rop] | GX_PATTERN_ONES;
316	pCg6->fbc->bg = 0xff;
317    } else {
318	/* draw background */
319	pCg6->fbc->alu = Cg6OpaqueStippleROP[rop] | GX_PATTERN_ONES;
320	pCg6->fbc->bg = bg;
321    }
322    pCg6->fbc->fg = fg;
323    pCg6->fbc->incx = 32;
324    pCg6->fbc->incy = 0;
325    pCg6->fbc->s = 0;
326    pCg6->fbc->pm = planemask;
327}
328
329static void
330Cg6SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
331			int x, int y, int w, int h,
332			int skipleft )
333{
334    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
335
336    pCg6->scan_x = x;
337    pCg6->scan_xe = x + w - 1;
338    pCg6->scan_y = y;
339
340    /*
341     * we need to clip the left and right margins of what we're going to draw or
342     * we'll end up with garbage left or right
343     */
344    pCg6->fbc->clipminx = x + skipleft;
345    pCg6->fbc->clipmaxx = x + w - 1;
346    pCg6->words_in_scanline = ((w + 31) >> 5);
347}
348
349static void
350Cg6SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
351{
352    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
353    int i;
354
355    /*
356     * the GX is WEIRD. if we tell it to draw n pixels it will fill the entire
357     * line with whatever we feed into the font register. When we write the next
358     * word it draws the entire line AGAIN. So we turn on clipping and pretend
359     * to write only 32 pixels...
360     */
361    pCg6->fbc->x0 = pCg6->scan_x;
362    pCg6->fbc->x1 = pCg6->scan_x + 31;
363    pCg6->fbc->y0 = pCg6->scan_y;
364    for (i = 0; i < pCg6->words_in_scanline; i++) {
365	pCg6->fbc->font = pCg6->scanline[i];
366    }
367    pCg6->scan_y++;
368}
369
370static void
371Cg6SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
372    unsigned int planemask)
373{
374    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
375
376    waitReady(pCg6);
377    unClip(pCg6);
378
379    pCg6->fbc->fg = color;
380    pCg6->fbc->mode = GX_BLIT_NOSRC;
381    pCg6->fbc->s = 0;
382    pCg6->fbc->alu = Cg6DrawROP[rop];
383    pCg6->fbc->pm = planemask;
384}
385
386static void
387Cg6SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
388    int y2, int flags)
389{
390    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
391
392    /*
393     * XXX we're blatantly ignoring the flags parameter which could tell us not
394     * to draw the last point. Xsun simply reads it from the framebuffer and
395     * puts it back after drawing the line but that would mean we have to wait
396     * until the line is actually drawn. On the other hand - line drawing is
397     * pretty fast so we won't lose too much speed
398     */
399    waitReady(pCg6);
400    pCg6->fbc->aliney = y1;
401    pCg6->fbc->alinex = x1;
402    pCg6->fbc->aliney = y2;
403    pCg6->fbc->alinex = x2;
404    runDraw(pCg6);
405}
406
407static void
408Cg6SetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right,
409			 int bottom)
410{
411    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
412
413    pCg6->fbc->clipminx = pCg6->clipxa = left;
414    pCg6->fbc->clipminy = top;
415    pCg6->fbc->clipmaxx = pCg6->clipxe = right;
416    pCg6->fbc->clipmaxy = bottom;
417}
418
419static void
420Cg6DisableClipping(ScrnInfoPtr pScrn)
421{
422    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
423
424    pCg6->fbc->clipminx = pCg6->clipxa = 0;
425    pCg6->fbc->clipminy = 0;
426    pCg6->fbc->clipmaxx = pCg6->clipxe = pCg6->width;
427    pCg6->fbc->clipmaxy = pCg6->maxheight;
428}
429
430int
431CG6AccelInit(ScrnInfoPtr pScrn)
432{
433    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
434    XAAInfoRecPtr pXAAInfo = pCg6->pXAA;
435
436    pXAAInfo->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
437    pXAAInfo->maxOffPixWidth = pCg6->width;
438    pXAAInfo->maxOffPixHeight = pCg6->maxheight;
439
440    Cg6InitEngine(pCg6);
441
442    /* wait until the engine is idle and remove clipping */
443    pXAAInfo->Sync = Cg6Sync;
444
445    /* clipping */
446    pXAAInfo->SetClippingRectangle = Cg6SetClippingRectangle;
447    pXAAInfo->DisableClipping = Cg6DisableClipping;
448    pXAAInfo->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
449        HARDWARE_CLIP_SOLID_FILL |
450        /*HARDWARE_CLIP_MONO_8x8_FILL |
451        HARDWARE_CLIP_COLOR_8x8_FILL |*/
452        HARDWARE_CLIP_SOLID_LINE;
453
454    /* Screen-to-screen copy */
455    pXAAInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
456    pXAAInfo->SetupForScreenToScreenCopy = Cg6SetupForScreenToScreenCopy;
457    pXAAInfo->SubsequentScreenToScreenCopy =
458        Cg6SubsequentScreenToScreenCopy;
459
460    /* Solid fills */
461    pXAAInfo->SetupForSolidFill = Cg6SetupForSolidFill;
462    pXAAInfo->SubsequentSolidFillRect = Cg6SubsequentSolidFillRect;
463
464    /* TODO: add pattern fills */
465
466    /* colour expansion */
467    pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
468	LEFT_EDGE_CLIPPING|SCANLINE_PAD_DWORD;
469    pXAAInfo->NumScanlineColorExpandBuffers = 1;
470    pCg6->buffers[0] = (unsigned char *)pCg6->scanline;
471    pXAAInfo->ScanlineColorExpandBuffers = pCg6->buffers;
472    pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
473	Cg6SetupForCPUToScreenColorExpandFill;
474    pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
475	Cg6SubsequentScanlineCPUToScreenColorExpandFill;
476    pXAAInfo->SubsequentColorExpandScanline =
477	Cg6SubsequentColorExpandScanline;
478
479    /* line drawing */
480    pXAAInfo->SetupForSolidLine = Cg6SetupForSolidLine;
481    pXAAInfo->SubsequentSolidTwoPointLine = Cg6SubsequentSolidTwoPointLine;
482    pXAAInfo->SolidLineFlags = BIT_ORDER_IN_BYTE_MSBFIRST;
483    /*
484     * apparently the hardware can't do dashed lines, only lines with patterns
485     * which isn't useful
486     */
487
488    /* TODO: add host-to-vram colour blits */
489
490    return 0;
491}
492
493Bool
494Cg6DGAInit(ScreenPtr pScreen)
495{
496    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
497    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
498    DGAModePtr mode;
499    int result;
500
501    mode = xnfcalloc(sizeof(DGAModeRec), 1);
502    if (mode == NULL) {
503        xf86Msg(X_WARNING, "%s: DGA setup failed, cannot allocate memory\n",
504            pCg6->psdp->device);
505        return FALSE;
506    }
507
508    mode->mode = pScrn->modes;
509    mode->flags = DGA_PIXMAP_AVAILABLE | DGA_CONCURRENT_ACCESS;
510    if(!pCg6->NoAccel) {
511        mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
512    }
513
514    mode->imageWidth = mode->pixmapWidth = mode->viewportWidth =
515	pScrn->virtualX;
516    mode->imageHeight = mode->pixmapHeight = mode->viewportHeight =
517	pScrn->virtualY;
518
519    mode->bytesPerScanline = mode->imageWidth;
520
521    mode->byteOrder = pScrn->imageByteOrder;
522    mode->depth = 8;
523    mode->bitsPerPixel = 8;
524    mode->red_mask = pScrn->mask.red;
525    mode->green_mask = pScrn->mask.green;
526    mode->blue_mask = pScrn->mask.blue;
527
528    mode->visualClass = PseudoColor;
529    mode->address = pCg6->fb;
530
531    result = DGAInit(pScreen, &Cg6_DGAFuncs, mode, 1);
532
533    if (result) {
534    	xf86Msg(X_INFO, "%s: DGA initialized\n",
535            pCg6->psdp->device);
536    } else {
537     	xf86Msg(X_WARNING, "%s: DGA setup failed\n",
538            pCg6->psdp->device);
539    }
540}
541
542static Bool
543Cg6_OpenFramebuffer(ScrnInfoPtr pScrn, char **name,
544				unsigned int *mem,
545				unsigned int *size, unsigned int *offset,
546				unsigned int *extra)
547{
548    Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn);
549
550    *name = pCg6->psdp->device;
551
552    *mem = CG6_RAM_VOFF;
553    *size = pCg6->vidmem;
554    *offset = 0;
555    *extra = 0;
556
557    return TRUE;
558}
559
560static Bool
561Cg6_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
562{
563    /*
564     * Nothing to do, we currently only support one mode
565     * and we are always in it.
566     */
567    return TRUE;
568}
569
570static void
571Cg6_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
572{
573     /* We don't support viewports, so... */
574}
575
576static int
577Cg6_GetViewport(ScrnInfoPtr pScrn)
578{
579    /* No viewports, none pending... */
580    return 0;
581}
582
583static void
584Cg6_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
585{
586
587    Cg6SetupForSolidFill(pScrn, color, GXset, 8);
588    Cg6SubsequentSolidFillRect(pScrn, x, y, w, h);
589}
590
591static void
592Cg6_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy,
593			 int w, int h, int dstx, int dsty)
594{
595
596    Cg6SetupForScreenToScreenCopy(pScrn, 0, 0, GXcopy, 8, 0);
597    Cg6SubsequentScreenToScreenCopy(pScrn, srcx, srcy, dstx, dsty, w, h);
598}
599