Indentation fix, cleanup.
[AROS.git] / arch / all-native / hidd / vga / bitmap.c
blobc27c5fff26032d398df523bff53a9921708016d2
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/graphics.h>
27 #include <assert.h>
29 #include "vgahw.h"
30 #include "vga.h"
31 #include "vgaclass.h"
33 #include "bitmap.h"
35 #include LC_LIBDEFS_FILE
37 void vgaRestore(struct vgaHWRec *);
38 int vgaInitMode(struct vgaModeDesc *, struct vgaHWRec *);
39 void vgaLoadPalette(struct vgaHWRec *, unsigned char *);
41 #define MNAME_ROOT(x) PCVGABM__Root__ ## x
42 #define MNAME_BM(x) PCVGABM__Hidd_BitMap__ ## x
44 /*********** BitMap::New() *************************************/
46 OOP_Object *PCVGABM__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
48 EnterFunc(bug("VGAGfx.BitMap::New()\n"));
50 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
51 D(bug("[VGABitMap] Object created by superclass: 0x%p\n"));
52 if (o)
54 struct bitmap_data *data;
55 OOP_Object *gfxhidd, *sync, *pf;
56 IPTR modeid = vHidd_ModeID_Invalid;
57 IPTR width, height, depth;
58 IPTR dwidth, dheight;
59 IPTR displayable = FALSE;
61 data = OOP_INST_DATA(cl, o);
63 /* clear all data */
64 memset(data, 0, sizeof(struct bitmap_data));
66 /* Get attr values */
67 OOP_GetAttr(o, aHidd_BitMap_ModeID , &modeid );
68 OOP_GetAttr(o, aHidd_BitMap_Width , &width );
69 OOP_GetAttr(o, aHidd_BitMap_Height , &height );
70 OOP_GetAttr(o, aHidd_BitMap_Displayable, &displayable);
71 OOP_GetAttr(o, aHidd_BitMap_PixFmt , (IPTR *)&pf );
72 D(bug("[VGABitMap] PixFmt object: 0x%p\n", pf));
73 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
75 D(bug("[VGABitMap] Size: %lux%lu, depth: %lu\n", width, height, depth));
76 D(bug("[VGABitMap] Displayable: %ld\n", displayable));
77 ASSERT (width != 0 && height != 0 && depth != 0);
79 data->width = width;
80 data->height = height;
81 data->bpp = depth;
83 if (modeid != vHidd_ModeID_Invalid) {
85 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (IPTR *)&gfxhidd);
86 HIDD_Gfx_GetMode(gfxhidd, modeid, &sync, &pf);
87 OOP_GetAttr(sync, aHidd_Sync_HDisp, &dwidth);
88 OOP_GetAttr(sync, aHidd_Sync_VDisp, &dheight);
89 data->disp_width = dwidth;
90 data->disp_height = dheight;
91 D(bug("[VGABitMap] Display size: %dx%d\n", dwidth, dheight));
94 width=(width+15) & ~15;
95 data->bpr = width;
96 data->VideoData = AllocVec(width*height,MEMF_PUBLIC|MEMF_CLEAR);
97 D(bug("[VGABitMap] Allocated videodata at 0x%p\n", data->VideoData));
98 if (data->VideoData) {
99 struct TagItem tags[2];
101 tags[0].ti_Tag = aHidd_ChunkyBM_Buffer;
102 tags[0].ti_Data = (IPTR)data->VideoData;
103 tags[1].ti_Tag = TAG_END;
104 OOP_SetAttrs(o, tags);
106 /* If the bitmap is not displayable, we're done */
107 if (!displayable)
108 ReturnPtr("VGAGfx.BitMap::New()", OOP_Object *, o);
110 data->Regs = AllocVec(sizeof(struct vgaHWRec),MEMF_PUBLIC|MEMF_CLEAR);
111 D(bug("[VGABitMap] Registers at 0x%p\n", data->Regs));
113 Here there is brand new method of getting pixelclock data.
114 It was introduced here to make the code more portable. Besides
115 it may now be used as a base for creating other low level
116 video drivers
118 if (data->Regs) {
119 struct vgaModeDesc mode;
120 IPTR pixelc;
122 /* We should have got modeID from the bitmap */
123 if (modeid != vHidd_ModeID_Invalid)
125 mode.Width = dwidth;
126 mode.Height = dheight;
127 mode.Depth = depth;
128 OOP_GetAttr(sync, aHidd_Sync_PixelClock, &pixelc);
130 mode.clock = (pixelc > 26000000) ? 1 : 0;
131 mode.Flags = 0;
132 mode.HSkew = 0;
133 OOP_GetAttr(sync, aHidd_Sync_HDisp, &mode.HDisplay);
134 OOP_GetAttr(sync, aHidd_Sync_VDisp, &mode.VDisplay);
135 OOP_GetAttr(sync, aHidd_Sync_HSyncStart, &mode.HSyncStart);
136 OOP_GetAttr(sync, aHidd_Sync_VSyncStart, &mode.VSyncStart);
137 OOP_GetAttr(sync, aHidd_Sync_HSyncEnd, &mode.HSyncEnd);
138 OOP_GetAttr(sync, aHidd_Sync_VSyncEnd, &mode.VSyncEnd);
139 OOP_GetAttr(sync, aHidd_Sync_HTotal, &mode.HTotal);
140 OOP_GetAttr(sync, aHidd_Sync_VTotal, &mode.VTotal);
142 vgaInitMode(&mode, data->Regs);
143 vgaLoadPalette(data->Regs,(unsigned char *)NULL);
145 D(bug("[VGABitMap] Created displayable bitmap 0x%p, data 0x%p\n", o, data));
146 return o;
149 FreeVec(data->VideoData);
153 OOP_MethodID disp_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
154 OOP_CoerceMethod(cl, o, (OOP_Msg) &disp_mid);
157 o = NULL;
158 } /* if created object */
160 ReturnPtr("VGAGfx.BitMap::New()", OOP_Object *, o);
163 /********** Bitmap::Dispose() ***********************************/
165 VOID PCVGABM__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
167 struct bitmap_data *data = OOP_INST_DATA(cl, o);
168 EnterFunc(bug("VGAGfx.BitMap::Dispose()\n"));
170 FreeVec(data->VideoData);
171 FreeVec(data->Regs);
173 OOP_DoSuperMethod(cl, o, msg);
175 ReturnVoid("VGAGfx.BitMap::Dispose");
178 /********* BitMap::SetColors() ***************************/
180 void vgaDACLoad(struct vgaHWRec *, unsigned char, int);
182 BOOL MNAME_BM(SetColors)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_SetColors *msg)
184 struct bitmap_data *data = OOP_INST_DATA(cl, o);
185 HIDDT_PixelFormat *pf;
187 ULONG xc_i, col_i;
189 HIDDT_Pixel red, green, blue;
191 pf = BM_PIXFMT(o);
193 if ( vHidd_ColorModel_StaticPalette == HIDD_PF_COLMODEL(pf)
194 || vHidd_ColorModel_TrueColor == HIDD_PF_COLMODEL(pf) ) {
196 /* Superclass takes care of this case */
198 return OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
201 /* We have a vHidd_GT_Palette bitmap */
203 if (!OOP_DoSuperMethod(cl, o, (OOP_Msg)msg)) return FALSE;
204 if (!data->Regs)
205 return TRUE;
207 if ((msg->firstColor + msg->numColors) > (1 << data->bpp))
208 return FALSE;
211 for ( xc_i = msg->firstColor, col_i = 0;
212 col_i < msg->numColors;
213 xc_i ++, col_i ++ )
215 red = msg->colors[col_i].red >> 8;
216 green = msg->colors[col_i].green >> 8;
217 blue = msg->colors[col_i].blue >> 8;
219 /* Update DAC registers */
220 data->Regs->DAC[xc_i*3] = red >> 2;
221 data->Regs->DAC[xc_i*3+1] = green >> 2;
222 data->Regs->DAC[xc_i*3+2] = blue >> 2;
224 msg->colors[col_i].pixval = xc_i;
227 /* Restore palette if displayed */
228 if (data->disp) {
229 ObtainSemaphore(&XSD(cl)->HW_acc);
230 vgaDACLoad(data->Regs, msg->firstColor, msg->numColors);
231 ReleaseSemaphore(&XSD(cl)->HW_acc);
234 return TRUE;
237 /********* BitMap::PutPixel() ***************************/
238 // FIXME: in theory we shouldn't need this method since the superclass implements it
240 VOID MNAME_BM(PutPixel)(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
242 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
243 return;
246 /*** BitMap::Set() *******************************************/
248 VOID MNAME_ROOT(Set)(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
250 struct bitmap_data *data = OOP_INST_DATA(cl, o);
251 struct TagItem *tag, *tstate;
252 ULONG idx;
253 int limit;
254 int xoffset = data->xoffset;
255 int yoffset = data->yoffset;
257 tstate = msg->attrList;
258 while((tag = NextTagItem(&tstate)))
260 if(IS_BM_ATTR(tag->ti_Tag, idx))
262 switch(idx)
264 case aoHidd_BitMap_Visible:
265 data->disp = tag->ti_Data;
266 D(bug("[VGAGfx] BitMap::Visible set to %d\n", data->disp));
267 if (data->disp) {
268 struct Box box;
270 /* Program video mode on the card */
271 bug("\x03");
272 vgaRestore(data->Regs);
273 /* If our bitmap is smaller than display area,
274 we need to clear two rectangles: to the right
275 and to the bottom of the used framebuffer
276 portion */
277 if (data->disp_width > data->width) {
278 box.x1 = data->width;
279 box.y1 = 0;
280 box.x2 = data->disp_width - 1;
281 box.y2 = data->height - 1;
282 vgaEraseArea(data, &box);
284 if (data->disp_height > data->height) {
285 box.x1 = 0;
286 box.y1 = data->height;
287 box.x2 = data->width - 1;
288 box.y2 = data->disp_height - 1;
289 vgaEraseArea(data, &box);
292 break;
293 case aoHidd_BitMap_LeftEdge:
294 xoffset = tag->ti_Data;
295 limit = data->disp_width - data->width;
296 if (xoffset > 0)
297 xoffset = 0;
298 else if (xoffset < limit)
299 xoffset = limit;
300 break;
301 case aoHidd_BitMap_TopEdge:
302 yoffset = tag->ti_Data;
303 limit = data->disp_height - data->height;
304 if (yoffset > 0)
305 yoffset = 0;
306 else if (yoffset < limit)
307 yoffset = limit;
308 break;
312 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
314 if ((xoffset != data->xoffset) || (yoffset != data->yoffset)) {
315 data->xoffset = xoffset;
316 data->yoffset = yoffset;
318 if (data->disp) {
319 struct Box box = {0, 0, data->disp_width - 1, data->disp_height - 1};
321 ObtainSemaphore(&XSD(cl)->HW_acc);
322 vgaRefreshArea(data, &box);
323 draw_mouse(XSD(cl));
324 ReleaseSemaphore(&XSD(cl)->HW_acc);
329 VOID MNAME_ROOT(Get)(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
331 struct bitmap_data *data = OOP_INST_DATA(cl, o);
332 ULONG idx;
334 if (IS_VGABM_ATTR(msg->attrID, idx)) {
335 switch (idx) {
336 case aoHidd_VGABitMap_Drawable:
337 *msg->storage = (IPTR)data->VideoData;
338 return;
340 } else if (IS_BM_ATTR(msg->attrID, idx)) {
341 switch (idx) {
342 case aoHidd_BitMap_LeftEdge:
343 *msg->storage = data->xoffset;
344 return;
345 case aoHidd_BitMap_TopEdge:
346 *msg->storage = data->yoffset;
347 return;
348 case aoHidd_BitMap_Visible:
349 *msg->storage = data->disp;
350 return;
353 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
356 /*** BitMap::UpdateRect() *******************************************/
358 VOID PCVGABM__Hidd_BitMap__UpdateRect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_UpdateRect *msg)
360 struct bitmap_data *data = OOP_INST_DATA(cl, o);
361 int left = msg->x + data->xoffset;
362 int top = msg->y + data->yoffset;
363 int right = left + msg->width - 1;
364 int bottom = top + msg->height - 1;
366 if ((right < 0) || (bottom < 0))
367 return;
368 if (left < 0)
369 left = 0;
370 if (top < 0)
371 top = 0;
373 if (data->disp)
375 ObtainSemaphore(&XSD(cl)->HW_acc);
377 if ((msg->width == 1) && (msg->height == 1))
378 vgaRefreshPixel(data, left, top);
379 else {
380 struct Box box = {left, top, right, bottom};
382 vgaRefreshArea(data, &box);
385 if ( ( (XSD(cl)->mouseX + XSD(cl)->mouseW - 1 >= left) &&
386 (XSD(cl)->mouseX <= right) ) ||
387 ( (XSD(cl)->mouseY + XSD(cl)->mouseH - 1 >= top) &&
388 (XSD(cl)->mouseY <= bottom) ) )
389 draw_mouse(XSD(cl));
391 ReleaseSemaphore(&XSD(cl)->HW_acc);