2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
5 Desc: Bitmap class for VGA Hidd.
11 #include <aros/debug.h>
13 #define __OOP_NOATTRBASES__
15 #include <proto/oop.h>
16 #include <proto/utility.h>
18 #include <exec/memory.h>
19 #include <exec/lists.h>
21 #include <graphics/rastport.h>
22 #include <graphics/gfx.h>
25 #include <aros/symbolsets.h>
31 #include "vgagfx_support.h"
33 #include LC_LIBDEFS_FILE
35 void vgaRestore(struct vgaHWRec
*);
36 int vgaInitMode(struct vgaModeDesc
*, struct vgaHWRec
*);
37 void vgaLoadPalette(struct vgaHWRec
*, unsigned char *);
39 #define MNAME_ROOT(x) VGAGfxBM__Root__ ## x
40 #define MNAME_BM(x) VGAGfxBM__Hidd_BitMap__ ## x
42 /*********** BitMap::New() *************************************/
44 OOP_Object
*VGAGfxBM__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
46 EnterFunc(bug("VGAGfx.BitMap::New()\n"));
48 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
49 D(bug("[VGAGfx:BitMap] Object created by superclass: 0x%p\n"));
52 struct VGAGfxBitMapData
*data
;
53 OOP_Object
*gfxhidd
, *sync
, *pf
;
54 IPTR modeid
= vHidd_ModeID_Invalid
;
55 IPTR width
, height
, depth
;
57 IPTR displayable
= FALSE
;
59 data
= OOP_INST_DATA(cl
, o
);
62 memset(data
, 0, sizeof(struct VGAGfxBitMapData
));
65 OOP_GetAttr(o
, aHidd_BitMap_ModeID
, &modeid
);
66 OOP_GetAttr(o
, aHidd_BitMap_Width
, &width
);
67 OOP_GetAttr(o
, aHidd_BitMap_Height
, &height
);
68 OOP_GetAttr(o
, aHidd_BitMap_Displayable
, &displayable
);
69 OOP_GetAttr(o
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
70 D(bug("[VGAGfx:BitMap] PixFmt object: 0x%p\n", pf
));
71 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
73 D(bug("[VGAGfx:BitMap] Size: %lux%lu, depth: %lu\n", width
, height
, depth
));
74 D(bug("[VGAGfx:BitMap] Displayable: %ld\n", displayable
));
75 ASSERT (width
!= 0 && height
!= 0 && depth
!= 0);
78 data
->height
= height
;
81 if (modeid
!= vHidd_ModeID_Invalid
) {
83 OOP_GetAttr(o
, aHidd_BitMap_GfxHidd
, (IPTR
*)&gfxhidd
);
84 HIDD_Gfx_GetMode(gfxhidd
, modeid
, &sync
, &pf
);
85 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &dwidth
);
86 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &dheight
);
87 data
->disp_width
= dwidth
;
88 data
->disp_height
= dheight
;
89 D(bug("[VGAGfx:BitMap] Display size: %dx%d\n", dwidth
, dheight
));
92 width
=(width
+15) & ~15;
94 data
->VideoData
= AllocVec(width
*height
,MEMF_PUBLIC
|MEMF_CLEAR
);
95 D(bug("[VGAGfx:BitMap] Allocated videodata at 0x%p\n", data
->VideoData
));
96 if (data
->VideoData
) {
97 struct TagItem tags
[2];
99 tags
[0].ti_Tag
= aHidd_ChunkyBM_Buffer
;
100 tags
[0].ti_Data
= (IPTR
)data
->VideoData
;
101 tags
[1].ti_Tag
= TAG_END
;
102 OOP_SetAttrs(o
, tags
);
104 /* If the bitmap is not displayable, we're done */
106 ReturnPtr("VGAGfx.BitMap::New()", OOP_Object
*, o
);
108 data
->Regs
= AllocVec(sizeof(struct vgaHWRec
),MEMF_PUBLIC
|MEMF_CLEAR
);
109 D(bug("[VGAGfx:BitMap] Registers at 0x%p\n", data
->Regs
));
111 Here there is brand new method of getting pixelclock data.
112 It was introduced here to make the code more portable. Besides
113 it may now be used as a base for creating other low level
117 struct vgaModeDesc mode
;
120 /* We should have got modeID from the bitmap */
121 if (modeid
!= vHidd_ModeID_Invalid
)
124 mode
.Height
= dheight
;
126 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &pixelc
);
128 mode
.clock
= (pixelc
> 26000000) ? 1 : 0;
131 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &mode
.HDisplay
);
132 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &mode
.VDisplay
);
133 OOP_GetAttr(sync
, aHidd_Sync_HSyncStart
, &mode
.HSyncStart
);
134 OOP_GetAttr(sync
, aHidd_Sync_VSyncStart
, &mode
.VSyncStart
);
135 OOP_GetAttr(sync
, aHidd_Sync_HSyncEnd
, &mode
.HSyncEnd
);
136 OOP_GetAttr(sync
, aHidd_Sync_VSyncEnd
, &mode
.VSyncEnd
);
137 OOP_GetAttr(sync
, aHidd_Sync_HTotal
, &mode
.HTotal
);
138 OOP_GetAttr(sync
, aHidd_Sync_VTotal
, &mode
.VTotal
);
140 vgaInitMode(&mode
, data
->Regs
);
141 vgaLoadPalette(data
->Regs
,(unsigned char *)NULL
);
143 D(bug("[VGAGfx:BitMap] Created displayable bitmap 0x%p, data 0x%p\n", o
, data
));
147 FreeVec(data
->VideoData
);
151 OOP_MethodID disp_mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
152 OOP_CoerceMethod(cl
, o
, (OOP_Msg
) &disp_mid
);
156 } /* if created object */
158 ReturnPtr("VGAGfx.BitMap::New()", OOP_Object
*, o
);
161 /********** Bitmap::Dispose() ***********************************/
163 VOID
VGAGfxBM__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
165 struct VGAGfxBitMapData
*data
= OOP_INST_DATA(cl
, o
);
166 EnterFunc(bug("VGAGfx.BitMap::Dispose()\n"));
168 FreeVec(data
->VideoData
);
171 OOP_DoSuperMethod(cl
, o
, msg
);
173 ReturnVoid("VGAGfx.BitMap::Dispose");
176 /********* BitMap::SetColors() ***************************/
178 void vgaDACLoad(struct vgaHWRec
*, unsigned char, int);
180 BOOL
MNAME_BM(SetColors
)(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_SetColors
*msg
)
182 struct VGAGfxBitMapData
*data
= OOP_INST_DATA(cl
, o
);
183 HIDDT_PixelFormat
*pf
;
187 HIDDT_Pixel red
, green
, blue
;
191 if ( vHidd_ColorModel_StaticPalette
== HIDD_PF_COLMODEL(pf
)
192 || vHidd_ColorModel_TrueColor
== HIDD_PF_COLMODEL(pf
) ) {
194 /* Superclass takes care of this case */
196 return OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
199 /* We have a vHidd_GT_Palette bitmap */
201 if (!OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
)) return FALSE
;
205 if ((msg
->firstColor
+ msg
->numColors
) > (1 << data
->bpp
))
209 for ( xc_i
= msg
->firstColor
, col_i
= 0;
210 col_i
< msg
->numColors
;
213 red
= msg
->colors
[col_i
].red
>> 8;
214 green
= msg
->colors
[col_i
].green
>> 8;
215 blue
= msg
->colors
[col_i
].blue
>> 8;
217 /* Update DAC registers */
218 data
->Regs
->DAC
[xc_i
*3] = red
>> 2;
219 data
->Regs
->DAC
[xc_i
*3+1] = green
>> 2;
220 data
->Regs
->DAC
[xc_i
*3+2] = blue
>> 2;
222 msg
->colors
[col_i
].pixval
= xc_i
;
225 /* Restore palette if displayed */
227 ObtainSemaphore(&XSD(cl
)->HW_acc
);
228 vgaDACLoad(data
->Regs
, msg
->firstColor
, msg
->numColors
);
229 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
235 /********* BitMap::PutPixel() ***************************/
236 // FIXME: in theory we shouldn't need this method since the superclass implements it
238 VOID
MNAME_BM(PutPixel
)(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPixel
*msg
)
240 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
244 /*** BitMap::Set() *******************************************/
246 VOID
MNAME_ROOT(Set
)(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Set
*msg
)
248 struct VGAGfxBitMapData
*data
= OOP_INST_DATA(cl
, o
);
249 struct TagItem
*tag
, *tstate
;
252 int xoffset
= data
->xoffset
;
253 int yoffset
= data
->yoffset
;
255 tstate
= msg
->attrList
;
256 while((tag
= NextTagItem(&tstate
)))
258 if(IS_BM_ATTR(tag
->ti_Tag
, idx
))
262 case aoHidd_BitMap_Visible
:
263 data
->disp
= tag
->ti_Data
;
264 D(bug("[VGAGfx:BitMap] Visible set to %d\n", data
->disp
));
268 /* Program video mode on the card */
270 vgaRestore(data
->Regs
);
271 /* If our bitmap is smaller than display area,
272 we need to clear two rectangles: to the right
273 and to the bottom of the used framebuffer
275 if (data
->disp_width
> data
->width
) {
276 box
.x1
= data
->width
;
278 box
.x2
= data
->disp_width
- 1;
279 box
.y2
= data
->height
- 1;
280 vgaEraseArea(data
, &box
);
282 if (data
->disp_height
> data
->height
) {
284 box
.y1
= data
->height
;
285 box
.x2
= data
->width
- 1;
286 box
.y2
= data
->disp_height
- 1;
287 vgaEraseArea(data
, &box
);
291 case aoHidd_BitMap_LeftEdge
:
292 xoffset
= tag
->ti_Data
;
293 limit
= data
->disp_width
- data
->width
;
296 else if (xoffset
< limit
)
299 case aoHidd_BitMap_TopEdge
:
300 yoffset
= tag
->ti_Data
;
301 limit
= data
->disp_height
- data
->height
;
304 else if (yoffset
< limit
)
310 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
312 if ((xoffset
!= data
->xoffset
) || (yoffset
!= data
->yoffset
)) {
313 data
->xoffset
= xoffset
;
314 data
->yoffset
= yoffset
;
317 struct Box box
= {0, 0, data
->disp_width
- 1, data
->disp_height
- 1};
319 ObtainSemaphore(&XSD(cl
)->HW_acc
);
320 vgaRefreshArea(data
, &box
);
322 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
327 VOID
MNAME_ROOT(Get
)(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
329 struct VGAGfxBitMapData
*data
= OOP_INST_DATA(cl
, o
);
332 if (IS_VGABM_ATTR(msg
->attrID
, idx
)) {
334 case aoHidd_VGABitMap_Drawable
:
335 *msg
->storage
= (IPTR
)data
->VideoData
;
338 } else if (IS_BM_ATTR(msg
->attrID
, idx
)) {
340 case aoHidd_BitMap_LeftEdge
:
341 *msg
->storage
= data
->xoffset
;
343 case aoHidd_BitMap_TopEdge
:
344 *msg
->storage
= data
->yoffset
;
346 case aoHidd_BitMap_Visible
:
347 *msg
->storage
= data
->disp
;
351 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
354 /*** BitMap::UpdateRect() *******************************************/
356 VOID
VGAGfxBM__Hidd_BitMap__UpdateRect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_UpdateRect
*msg
)
358 struct VGAGfxBitMapData
*data
= OOP_INST_DATA(cl
, o
);
359 int left
= msg
->x
+ data
->xoffset
;
360 int top
= msg
->y
+ data
->yoffset
;
361 int right
= left
+ msg
->width
- 1;
362 int bottom
= top
+ msg
->height
- 1;
364 if ((right
< 0) || (bottom
< 0))
373 ObtainSemaphore(&XSD(cl
)->HW_acc
);
375 if ((msg
->width
== 1) && (msg
->height
== 1))
376 vgaRefreshPixel(data
, left
, top
);
378 struct Box box
= {left
, top
, right
, bottom
};
380 vgaRefreshArea(data
, &box
);
383 if ( ( (XSD(cl
)->mouseX
+ XSD(cl
)->mouseW
- 1 >= left
) &&
384 (XSD(cl
)->mouseX
<= right
) ) ||
385 ( (XSD(cl
)->mouseY
+ XSD(cl
)->mouseH
- 1 >= top
) &&
386 (XSD(cl
)->mouseY
<= bottom
) ) )
389 ReleaseSemaphore(&XSD(cl
)->HW_acc
);