1 /*
2  * PROJECT:         ReactOS VGA display driver
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            drivers/video/displays/vga/objects/paint.c
5  * PURPOSE:
6  * PROGRAMMERS:
7  */
8 
9 #include <vgaddi.h>
10 
11 BOOL VGADDIFillSolid(SURFOBJ *Surface, RECTL Dimensions, ULONG iColor)
12 {
13     int x, y, x2, y2, w, h, j;
14     ULONG orgx, pre1, midpre1, tmppre1;
15     //ULONG offset, orgpre1;
16     int ileftpix, imidpix, irightpix;
17 /*    double leftpix, midpix, rightpix;*/
18 
19     /* Swap dimensions so that x, y are at topmost left */
20     if ( Dimensions.right < Dimensions.left )
21     {
22         x  = Dimensions.right;
23         x2 = Dimensions.left;
24     }
25     else
26     {
27         x2 = Dimensions.right;
28         x  = Dimensions.left;
29     }
30     if ( Dimensions.bottom < Dimensions.top )
31     {
32         y  = Dimensions.bottom;
33         y2 = Dimensions.top;
34     }
35     else
36     {
37         y2 = Dimensions.bottom;
38         y  = Dimensions.top;
39     }
40 
41     /* Calculate the width and height */
42     w = x2 - x;
43     h = y2 - y;
44 
45     DPRINT("VGADDIFillSolid: x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
46 
47     /* Calculate the starting offset */
48     //offset = xconv[x]+y80[y];
49 
50     /* Make a note of original x */
51     orgx = x;
52 
53     /* Calculate the left mask pixels, middle bytes and right mask pixel */
54     ileftpix = 7 - mod8(x-1);
55     irightpix = mod8(x+w);
56     imidpix = (w-ileftpix-irightpix) / 8;
57 
58     pre1 = xconv[(x-1)&~7] + y80[y];
59     //orgpre1=pre1;
60 
61     /* check for overlap ( very horizontally skinny rect ) */
62     if ( (ileftpix+irightpix) > w )
63     {
64         int mask = startmasks[ileftpix] & endmasks[irightpix];
65 
66         WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);     // set the mask
67         WRITE_PORT_UCHAR((PUCHAR)GRA_D,mask);
68 
69         tmppre1 = pre1;
70         for ( j = y; j < y+h; j++ )
71         {
72             READ_REGISTER_UCHAR ( vidmem+tmppre1 );
73             WRITE_REGISTER_UCHAR ( vidmem+tmppre1, iColor );
74             tmppre1 += 80;
75         }
76         return TRUE;
77     }
78 
79     if ( ileftpix > 0 )
80     {
81         /* Write left pixels */
82         WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);     // set the mask
83         WRITE_PORT_UCHAR((PUCHAR)GRA_D,startmasks[ileftpix]);
84 
85         tmppre1 = pre1;
86         for ( j = y; j < y+h; j++ )
87         {
88             READ_REGISTER_UCHAR(vidmem + tmppre1);
89             WRITE_REGISTER_UCHAR(vidmem + tmppre1, iColor);
90             tmppre1 += 80;
91         }
92 
93         /* Prepare new x for the middle */
94         x = orgx + 8;
95     }
96 
97     if ( imidpix > 0 )
98     {
99         midpre1=xconv[x] + y80[y];
100 
101         /* Set mask to all pixels in byte */
102         WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);
103 
104         WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xff);
105 
106         for ( j = y; j < y+h; j++ )
107         {
108             memset(vidmem+midpre1, iColor, imidpix); // write middle pixels, no need to read in latch because of the width
109             midpre1 += 80;
110         }
111     }
112 
113     x = orgx + w - irightpix;
114     pre1 = xconv[x] + y80[y];
115 
116     /* Write right pixels */
117     WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);     // set the mask bits
118     WRITE_PORT_UCHAR((PUCHAR)GRA_D,endmasks[irightpix]);
119 
120     for ( j = y; j < y+h; j++ )
121     {
122         READ_REGISTER_UCHAR(vidmem + pre1);
123         WRITE_REGISTER_UCHAR(vidmem + pre1, iColor);
124         pre1 += 80;
125     }
126 
127     return TRUE;
128 }
129 
130 BOOL VGADDIPaintRgn(
131     IN SURFOBJ *Surface,
132     IN CLIPOBJ *ClipRegion,
133     IN ULONG iColor,
134     IN MIX Mix,
135     IN BRUSHINST *BrushInst,
136     IN POINTL *BrushPoint)
137 {
138     RECT_ENUM RectEnum;
139     BOOL EnumMore;
140 
141     DPRINT("VGADDIPaintRgn: iMode: %d, iDComplexity: %d\n Color:%d\n", ClipRegion->iMode, ClipRegion->iDComplexity, iColor);
142     switch(ClipRegion->iMode)
143     {
144         case TC_RECTANGLES:
145 
146         /* Rectangular clipping can be handled without enumeration.
147            Note that trivial clipping is not possible, since the clipping
148            region defines the area to fill */
149 
150         if (ClipRegion->iDComplexity == DC_RECT)
151         {
152             DPRINT("VGADDIPaintRgn Rect:%d %d %d %d\n", ClipRegion->rclBounds.left, ClipRegion->rclBounds.top, ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom);
153             VGADDIFillSolid(Surface, ClipRegion->rclBounds, iColor);
154         }
155         else
156         {
157             /* Enumerate all the rectangles and draw them */
158 
159             CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0);
160 
161             do
162             {
163                 UINT i;
164                 EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
165                 DPRINT("EnumMore: %d, count: %d\n", EnumMore, RectEnum.c);
166                 for( i=0; i<RectEnum.c; i++)
167                 {
168                     DPRINT("VGADDI enum Rect:%d %d %d %d\n", RectEnum.arcl[i].left, RectEnum.arcl[i].top, RectEnum.arcl[i].right, RectEnum.arcl[i].bottom);
169                     VGADDIFillSolid(Surface, RectEnum.arcl[i], iColor);
170                 }
171             } while (EnumMore);
172         }
173         return TRUE;
174 
175         default:
176             return FALSE;
177     }
178 }
179 
180 
181 BOOL APIENTRY
182 DrvPaint(
183     IN SURFOBJ *Surface,
184     IN CLIPOBJ *ClipRegion,
185     IN BRUSHOBJ *Brush,
186     IN POINTL *BrushOrigin,
187     IN MIX Mix)
188 {
189     ULONG iSolidColor;
190 
191     iSolidColor = Brush->iSolidColor; // FIXME: Realizations and the like
192 
193     // If the foreground and background Mixes are the same,
194     // (LATER or if there's no brush mask)
195     // then see if we can use the solid brush accelerators
196 
197     // FIXME: Put in the mix switch below
198     // Brush color parameter doesn't matter for these rops
199     return(VGADDIPaintRgn(Surface, ClipRegion, iSolidColor, Mix, NULL, BrushOrigin));
200 
201     if ((Mix & 0xFF) == ((Mix >> 8) & 0xFF))
202     {
203         switch (Mix & 0xFF)
204         {
205             case 0:
206                 break;
207 
208             // FIXME: Implement all these millions of ROPs
209             // For now we don't support brushes -- everything is solid
210 
211             case R2_MASKNOTPEN:
212             case R2_NOTCOPYPEN:
213             case R2_XORPEN:
214             case R2_MASKPEN:
215             case R2_NOTXORPEN:
216             case R2_MERGENOTPEN:
217             case R2_COPYPEN:
218             case R2_MERGEPEN:
219             case R2_NOTMERGEPEN:
220             case R2_MASKPENNOT:
221             case R2_NOTMASKPEN:
222             case R2_MERGEPENNOT:
223 
224             // Rops that are implicit solid colors
225             case R2_NOT:
226             case R2_WHITE:
227             case R2_BLACK:
228 
229 
230             // FIXME: The Paint region belongs HERE
231 
232             case R2_NOP:
233                 return TRUE;
234 
235             default:
236                 break;
237         }
238     }
239 
240 /*
241 doBitBlt:
242 
243     // If VGADDIPaint can't do it, VGADDIBitBlt can.. or it might just loop back
244     // here and we have a nice infinite loop
245 
246     return( VGADDIBitBlt(Surface, (SURFOBJ *)NULL, (SURFOBJ *)NULL, ClipRegion,
247                         (XLATEOBJ *)NULL, &ClipRegion->rclBounds,
248                         NULL, (POINTL *)NULL, Brush, BrushOrigin,
249                         NULL) ); UNIMPLEMENTED */
250 }
251