wip prep commit in lieu of gfx subsystem update changes.
[AROS.git] / arch / all-native / hidd / vga / vgagfx_bitmapclass.c
blob487daadae4b8bc29f7bf606b6adfcaae3fddefbd
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Bitmap class for VGA Hidd.
6 Lang: English.
7 */
9 #define SDEBUG 0
10 #define DEBUG 0
11 #include <aros/debug.h>
13 #include <proto/oop.h>
14 #include <proto/utility.h>
16 #include <exec/memory.h>
17 #include <exec/lists.h>
19 #include <graphics/rastport.h>
20 #include <graphics/gfx.h>
21 #include <oop/oop.h>
23 #include <aros/symbolsets.h>
25 #include <hidd/gfx.h>
27 #include <assert.h>
29 #include "vgagfx_support.h"
30 #include "vgagfx_intern.h"
31 #include "vgagfx_hidd.h"
32 #include "vgagfx_bitmap.h"
34 #include LC_LIBDEFS_FILE
36 void vgaRestore(struct vgaHWRec *);
37 int vgaInitMode(struct vgaModeDesc *, struct vgaHWRec *);
38 void vgaLoadPalette(struct vgaHWRec *, unsigned char *);
40 #define MNAME_ROOT(x) VGAGfxBM__Root__ ## x
41 #define MNAME_BM(x) VGAGfxBM__Hidd_BitMap__ ## x
43 /*********** BitMap::New() *************************************/
45 OOP_Object *VGAGfxBM__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
47 EnterFunc(bug("VGAGfx.BitMap::New()\n"));
49 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
50 D(bug("[VGAGfx:BitMap] Object created by superclass: 0x%p\n"));
51 if (o)
53 struct VGAGfxBitMapData *data;
54 OOP_Object *gfxhidd, *sync, *pf;
55 IPTR modeid = vHidd_ModeID_Invalid;
56 IPTR width, height, depth;
57 IPTR dwidth, dheight;
58 IPTR displayable = FALSE;
60 data = OOP_INST_DATA(cl, o);
62 /* clear all data */
63 memset(data, 0, sizeof(struct VGAGfxBitMapData));
65 /* Get attr values */
66 OOP_GetAttr(o, aHidd_BitMap_ModeID , &modeid );
67 OOP_GetAttr(o, aHidd_BitMap_Width , &width );
68 OOP_GetAttr(o, aHidd_BitMap_Height , &height );
69 OOP_GetAttr(o, aHidd_BitMap_Displayable, &displayable);
70 OOP_GetAttr(o, aHidd_BitMap_PixFmt , (IPTR *)&pf );
71 D(bug("[VGAGfx:BitMap] PixFmt object: 0x%p\n", pf));
72 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
74 D(bug("[VGAGfx:BitMap] Size: %lux%lu, depth: %lu\n", width, height, depth));
75 D(bug("[VGAGfx:BitMap] Displayable: %ld\n", displayable));
76 ASSERT (width != 0 && height != 0 && depth != 0);
78 data->width = width;
79 data->height = height;
80 data->bpp = depth;
82 if (modeid != vHidd_ModeID_Invalid) {
84 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (IPTR *)&gfxhidd);
85 HIDD_Gfx_GetMode(gfxhidd, modeid, &sync, &pf);
86 OOP_GetAttr(sync, aHidd_Sync_HDisp, &dwidth);
87 OOP_GetAttr(sync, aHidd_Sync_VDisp, &dheight);
88 data->disp_width = dwidth;
89 data->disp_height = dheight;
90 D(bug("[VGAGfx:BitMap] Display size: %dx%d\n", dwidth, dheight));
93 width=(width+15) & ~15;
94 data->bpr = width;
95 data->VideoData = AllocVec(width*height,MEMF_PUBLIC|MEMF_CLEAR);
96 D(bug("[VGAGfx:BitMap] Allocated videodata at 0x%p\n", data->VideoData));
97 if (data->VideoData) {
98 struct TagItem tags[2];
100 tags[0].ti_Tag = aHidd_ChunkyBM_Buffer;
101 tags[0].ti_Data = (IPTR)data->VideoData;
102 tags[1].ti_Tag = TAG_END;
103 OOP_SetAttrs(o, tags);
105 /* If the bitmap is not displayable, we're done */
106 if (!displayable)
107 ReturnPtr("VGAGfx.BitMap::New()", OOP_Object *, o);
109 data->Regs = AllocVec(sizeof(struct vgaHWRec),MEMF_PUBLIC|MEMF_CLEAR);
110 D(bug("[VGAGfx:BitMap] Registers at 0x%p\n", data->Regs));
112 Here there is brand new method of getting pixelclock data.
113 It was introduced here to make the code more portable. Besides
114 it may now be used as a base for creating other low level
115 video drivers
117 if (data->Regs) {
118 struct vgaModeDesc mode;
119 IPTR pixelc;
121 /* We should have got modeID from the bitmap */
122 if (modeid != vHidd_ModeID_Invalid)
124 mode.Width = dwidth;
125 mode.Height = dheight;
126 mode.Depth = depth;
127 OOP_GetAttr(sync, aHidd_Sync_PixelClock, &pixelc);
129 mode.clock = (pixelc > 26000000) ? 1 : 0;
130 mode.Flags = 0;
131 mode.HSkew = 0;
132 OOP_GetAttr(sync, aHidd_Sync_HDisp, &mode.HDisplay);
133 OOP_GetAttr(sync, aHidd_Sync_VDisp, &mode.VDisplay);
134 OOP_GetAttr(sync, aHidd_Sync_HSyncStart, &mode.HSyncStart);
135 OOP_GetAttr(sync, aHidd_Sync_VSyncStart, &mode.VSyncStart);
136 OOP_GetAttr(sync, aHidd_Sync_HSyncEnd, &mode.HSyncEnd);
137 OOP_GetAttr(sync, aHidd_Sync_VSyncEnd, &mode.VSyncEnd);
138 OOP_GetAttr(sync, aHidd_Sync_HTotal, &mode.HTotal);
139 OOP_GetAttr(sync, aHidd_Sync_VTotal, &mode.VTotal);
141 vgaInitMode(&mode, data->Regs);
142 vgaLoadPalette(data->Regs,(unsigned char *)NULL);
144 D(bug("[VGAGfx:BitMap] Created displayable bitmap 0x%p, data 0x%p\n", o, data));
145 return o;
148 FreeVec(data->VideoData);
152 OOP_MethodID disp_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
153 OOP_CoerceMethod(cl, o, (OOP_Msg) &disp_mid);
156 o = NULL;
157 } /* if created object */
159 ReturnPtr("VGAGfx.BitMap::New()", OOP_Object *, o);
162 /********** Bitmap::Dispose() ***********************************/
164 VOID VGAGfxBM__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
166 struct VGAGfxBitMapData *data = OOP_INST_DATA(cl, o);
167 EnterFunc(bug("VGAGfx.BitMap::Dispose()\n"));
169 FreeVec(data->VideoData);
170 FreeVec(data->Regs);
172 OOP_DoSuperMethod(cl, o, msg);
174 ReturnVoid("VGAGfx.BitMap::Dispose");
177 /********* BitMap::SetColors() ***************************/
179 void vgaDACLoad(struct vgaHWRec *, unsigned char, int);
181 BOOL MNAME_BM(SetColors)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_SetColors *msg)
183 struct VGAGfxBitMapData *data = OOP_INST_DATA(cl, o);
184 HIDDT_PixelFormat *pf;
186 ULONG xc_i, col_i;
188 HIDDT_Pixel red, green, blue;
190 pf = BM_PIXFMT(o);
192 if ( vHidd_ColorModel_StaticPalette == HIDD_PF_COLMODEL(pf)
193 || vHidd_ColorModel_TrueColor == HIDD_PF_COLMODEL(pf) ) {
195 /* Superclass takes care of this case */
197 return OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
200 /* We have a vHidd_GT_Palette bitmap */
202 if (!OOP_DoSuperMethod(cl, o, (OOP_Msg)msg)) return FALSE;
203 if (!data->Regs)
204 return TRUE;
206 if ((msg->firstColor + msg->numColors) > (1 << data->bpp))
207 return FALSE;
210 for ( xc_i = msg->firstColor, col_i = 0;
211 col_i < msg->numColors;
212 xc_i ++, col_i ++ )
214 red = msg->colors[col_i].red >> 8;
215 green = msg->colors[col_i].green >> 8;
216 blue = msg->colors[col_i].blue >> 8;
218 /* Update DAC registers */
219 data->Regs->DAC[xc_i*3] = red >> 2;
220 data->Regs->DAC[xc_i*3+1] = green >> 2;
221 data->Regs->DAC[xc_i*3+2] = blue >> 2;
223 msg->colors[col_i].pixval = xc_i;
226 /* Restore palette if displayed */
227 if (data->disp) {
228 ObtainSemaphore(&XSD(cl)->HW_acc);
229 vgaDACLoad(data->Regs, msg->firstColor, msg->numColors);
230 ReleaseSemaphore(&XSD(cl)->HW_acc);
233 return TRUE;
236 /********* BitMap::PutPixel() ***************************/
237 // FIXME: in theory we shouldn't need this method since the superclass implements it
239 VOID MNAME_BM(PutPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
241 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
242 return;
245 /*** BitMap::Set() *******************************************/
247 VOID MNAME_ROOT(Set)(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
249 struct VGAGfxBitMapData *data = OOP_INST_DATA(cl, o);
250 struct TagItem *tag, *tstate;
251 ULONG idx;
252 int limit;
253 int xoffset = data->xoffset;
254 int yoffset = data->yoffset;
256 tstate = msg->attrList;
257 while((tag = NextTagItem(&tstate)))
259 if(IS_BM_ATTR(tag->ti_Tag, idx))
261 switch(idx)
263 case aoHidd_BitMap_Visible:
264 data->disp = tag->ti_Data;
265 D(bug("[VGAGfx:BitMap] Visible set to %d\n", data->disp));
266 if (data->disp) {
267 struct Box box;
269 /* Program video mode on the card */
270 bug("\x03");
271 vgaRestore(data->Regs);
272 /* If our bitmap is smaller than display area,
273 we need to clear two rectangles: to the right
274 and to the bottom of the used framebuffer
275 portion */
276 if (data->disp_width > data->width) {
277 box.x1 = data->width;
278 box.y1 = 0;
279 box.x2 = data->disp_width - 1;
280 box.y2 = data->height - 1;
281 vgaEraseArea(data, &box);
283 if (data->disp_height > data->height) {
284 box.x1 = 0;
285 box.y1 = data->height;
286 box.x2 = data->width - 1;
287 box.y2 = data->disp_height - 1;
288 vgaEraseArea(data, &box);
291 break;
292 case aoHidd_BitMap_LeftEdge:
293 xoffset = tag->ti_Data;
294 limit = data->disp_width - data->width;
295 if (xoffset > 0)
296 xoffset = 0;
297 else if (xoffset < limit)
298 xoffset = limit;
299 break;
300 case aoHidd_BitMap_TopEdge:
301 yoffset = tag->ti_Data;
302 limit = data->disp_height - data->height;
303 if (yoffset > 0)
304 yoffset = 0;
305 else if (yoffset < limit)
306 yoffset = limit;
307 break;
311 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
313 if ((xoffset != data->xoffset) || (yoffset != data->yoffset)) {
314 data->xoffset = xoffset;
315 data->yoffset = yoffset;
317 if (data->disp) {
318 struct Box box = {0, 0, data->disp_width - 1, data->disp_height - 1};
320 ObtainSemaphore(&XSD(cl)->HW_acc);
321 vgaRefreshArea(data, &box);
322 draw_mouse(XSD(cl));
323 ReleaseSemaphore(&XSD(cl)->HW_acc);
328 VOID MNAME_ROOT(Get)(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
330 struct VGAGfxBitMapData *data = OOP_INST_DATA(cl, o);
331 ULONG idx;
333 if (IS_VGABM_ATTR(msg->attrID, idx)) {
334 switch (idx) {
335 case aoHidd_VGABitMap_Drawable:
336 *msg->storage = (IPTR)data->VideoData;
337 return;
339 } else if (IS_BM_ATTR(msg->attrID, idx)) {
340 switch (idx) {
341 case aoHidd_BitMap_LeftEdge:
342 *msg->storage = data->xoffset;
343 return;
344 case aoHidd_BitMap_TopEdge:
345 *msg->storage = data->yoffset;
346 return;
347 case aoHidd_BitMap_Visible:
348 *msg->storage = data->disp;
349 return;
352 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
355 /*** BitMap::UpdateRect() *******************************************/
357 VOID VGAGfxBM__Hidd_BitMap__UpdateRect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_UpdateRect *msg)
359 struct VGAGfxBitMapData *data = OOP_INST_DATA(cl, o);
360 int left = msg->x + data->xoffset;
361 int top = msg->y + data->yoffset;
362 int right = left + msg->width - 1;
363 int bottom = top + msg->height - 1;
365 if ((right < 0) || (bottom < 0))
366 return;
367 if (left < 0)
368 left = 0;
369 if (top < 0)
370 top = 0;
372 if (data->disp)
374 ObtainSemaphore(&XSD(cl)->HW_acc);
376 if ((msg->width == 1) && (msg->height == 1))
377 vgaRefreshPixel(data, left, top);
378 else {
379 struct Box box = {left, top, right, bottom};
381 vgaRefreshArea(data, &box);
384 if ( ( (XSD(cl)->mouseX + XSD(cl)->mouseW - 1 >= left) &&
385 (XSD(cl)->mouseX <= right) ) ||
386 ( (XSD(cl)->mouseY + XSD(cl)->mouseH - 1 >= top) &&
387 (XSD(cl)->mouseY <= bottom) ) )
388 draw_mouse(XSD(cl));
390 ReleaseSemaphore(&XSD(cl)->HW_acc);