Hint added.
[AROS.git] / workbench / hidds / nouveau / nouveauclass.c
blob144c80d76401d049a3b3ff07f6a66b4ce9def35a
1 /*
2 Copyright © 2010-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "nouveau_intern.h"
7 #include "compositor.h"
9 #include <graphics/displayinfo.h>
10 #include <proto/utility.h>
11 #include <nouveau_drm.h>
13 #define DEBUG 0
14 #include <aros/debug.h>
15 #include <proto/oop.h>
17 #include "arosdrmmode.h"
19 #undef HiddPixFmtAttrBase
20 #undef HiddGfxAttrBase
21 #undef HiddGfxNouveauAttrBase
22 #undef HiddSyncAttrBase
23 #undef HiddBitMapAttrBase
24 #undef HiddCompositorAttrBase
25 #undef HiddBitMapNouveauAttrBase
27 #define HiddPixFmtAttrBase (SD(cl)->pixFmtAttrBase)
28 #define HiddGfxAttrBase (SD(cl)->gfxAttrBase)
29 #define HiddGfxNouveauAttrBase (SD(cl)->gfxNouveauAttrBase)
30 #define HiddSyncAttrBase (SD(cl)->syncAttrBase)
31 #define HiddBitMapAttrBase (SD(cl)->bitMapAttrBase)
32 #define HiddCompositorAttrBase (SD(cl)->compositorAttrBase)
33 #define HiddBitMapNouveauAttrBase (SD(cl)->bitMapNouveauAttrBase)
35 #define MAX_BITMAP_WIDTH 4096
36 #define MAX_BITMAP_HEIGHT 4096
37 #define GART_BUFFER_SIZE (12 * 1024 * 1024)
39 /* HELPER FUNCTIONS */
40 VOID HIDDNouveauShowCursor(OOP_Object * gfx, BOOL visible)
42 OOP_Class * cl = OOP_OCLASS(gfx);
43 struct HIDDNouveauData * gfxdata = OOP_INST_DATA(cl, gfx);
44 struct CardData * carddata = &(SD(cl)->carddata);
45 struct nouveau_device_priv * nvdev = nouveau_device(carddata->dev);
47 if (visible)
49 drmModeSetCursor(nvdev->fd, gfxdata->selectedcrtcid,
50 gfxdata->cursor->handle, 64, 64);
52 else
54 drmModeSetCursor(nvdev->fd, gfxdata->selectedcrtcid,
55 0, 64, 64);
59 static BOOL HIDDNouveauSelectConnectorCrtc(LONG fd, drmModeConnectorPtr * selectedconnector,
60 drmModeCrtcPtr * selectedcrtc)
62 *selectedconnector = NULL;
63 *selectedcrtc = NULL;
64 drmModeResPtr drmmode = NULL;
65 LONG i; ULONG crtc_id;
67 /* Get all components information */
68 drmmode = drmModeGetResources(fd);
69 if (!drmmode)
71 D(bug("[Nouveau] Not able to get resources information\n"));
72 return FALSE;
75 /* Selecting connector */
76 for (i = 0; i < drmmode->count_connectors; i++)
78 drmModeConnectorPtr connector = drmModeGetConnector(fd, drmmode->connectors[i]);
80 if (connector)
82 if (connector->connection == DRM_MODE_CONNECTED)
84 /* Found connected connector */
85 *selectedconnector = connector;
86 break;
89 drmModeFreeConnector(connector);
93 if (!(*selectedconnector))
95 D(bug("[Nouveau] No connected connector\n"));
96 drmModeFreeResources(drmmode);
97 return FALSE;
100 /* Selecting first available CRTC */
101 if (drmmode->count_crtcs > 0)
102 crtc_id = drmmode->crtcs[0];
103 else
104 crtc_id = 0;
106 *selectedcrtc = drmModeGetCrtc(fd, crtc_id);
107 if (!(*selectedcrtc))
109 D(bug("[Nouveau] Not able to get crtc information for crtc_id %d\n", crtc_id));
110 drmModeFreeConnector(*selectedconnector);
111 *selectedconnector = NULL;
112 drmModeFreeResources(drmmode);
113 return FALSE;
116 drmModeFreeResources(drmmode);
117 return TRUE;
120 #include <stdio.h>
122 static struct TagItem * HIDDNouveauCreateSyncTagsFromConnector(OOP_Class * cl, drmModeConnectorPtr connector)
124 struct TagItem * syncs = NULL;
125 ULONG modescount = connector->count_modes;
126 ULONG i;
128 if (modescount == 0)
129 return NULL;
131 /* Allocate enough structures */
132 syncs = HIDDNouveauAlloc(sizeof(struct TagItem) * modescount);
134 for (i = 0; i < modescount; i++)
136 struct TagItem * sync = HIDDNouveauAlloc(sizeof(struct TagItem) * 15);
137 LONG j = 0;
139 drmModeModeInfoPtr mode = &connector->modes[i];
141 sync[j].ti_Tag = aHidd_Sync_PixelClock; sync[j++].ti_Data = mode->clock;
143 sync[j].ti_Tag = aHidd_Sync_HDisp; sync[j++].ti_Data = mode->hdisplay;
144 sync[j].ti_Tag = aHidd_Sync_HSyncStart; sync[j++].ti_Data = mode->hsync_start;
145 sync[j].ti_Tag = aHidd_Sync_HSyncEnd; sync[j++].ti_Data = mode->hsync_end;
146 sync[j].ti_Tag = aHidd_Sync_HTotal; sync[j++].ti_Data = mode->htotal;
147 sync[j].ti_Tag = aHidd_Sync_HMin; sync[j++].ti_Data = mode->hdisplay;
148 sync[j].ti_Tag = aHidd_Sync_HMax; sync[j++].ti_Data = MAX_BITMAP_WIDTH;
150 sync[j].ti_Tag = aHidd_Sync_VDisp; sync[j++].ti_Data = mode->vdisplay;
151 sync[j].ti_Tag = aHidd_Sync_VSyncStart; sync[j++].ti_Data = mode->vsync_start;
152 sync[j].ti_Tag = aHidd_Sync_VSyncEnd; sync[j++].ti_Data = mode->vsync_end;
153 sync[j].ti_Tag = aHidd_Sync_VTotal; sync[j++].ti_Data = mode->vtotal;
154 sync[j].ti_Tag = aHidd_Sync_VMin; sync[j++].ti_Data = mode->vdisplay;
155 sync[j].ti_Tag = aHidd_Sync_VMax; sync[j++].ti_Data = MAX_BITMAP_HEIGHT;
157 /* Name */
158 STRPTR syncname = HIDDNouveauAlloc(32);
159 sprintf(syncname, "NV:%dx%d@%d", mode->hdisplay, mode->vdisplay, mode->vrefresh);
161 sync[j].ti_Tag = aHidd_Sync_Description; sync[j++].ti_Data = (IPTR)syncname;
163 sync[j].ti_Tag = TAG_DONE; sync[j++].ti_Data = 0UL;
165 syncs[i].ti_Tag = aHidd_Gfx_SyncTags;
166 syncs[i].ti_Data = (IPTR)sync;
169 return syncs;
172 /* This function assumes that the mode, crtc and output are already selected */
173 static BOOL HIDDNouveauShowBitmapForSelectedMode(OOP_Object * bm)
175 OOP_Class * cl = OOP_OCLASS(bm);
176 struct HIDDNouveauData * gfxdata = NULL;
177 struct HIDDNouveauBitMapData * bmdata = OOP_INST_DATA(cl, bm);
178 struct CardData * carddata = &(SD(cl)->carddata);
179 struct nouveau_device_priv *nvdev = nouveau_device(carddata->dev);
180 uint32_t output_ids[] = {0};
181 uint32_t output_count = 1;
182 IPTR e = (IPTR)NULL;
183 OOP_Object * gfx = NULL;
184 LONG ret;
186 LOCK_BITMAP
188 /* Check if passed bitmap has been registered as framebuffer */
189 if (bmdata->fbid == 0)
191 UNLOCK_BITMAP
192 return FALSE;
195 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
196 gfx = (OOP_Object *)e;
197 gfxdata = OOP_INST_DATA(OOP_OCLASS(gfx), gfx);
198 output_ids[0] = ((drmModeConnectorPtr)gfxdata->selectedconnector)->connector_id;
201 ret = drmModeSetCrtc(nvdev->fd, gfxdata->selectedcrtcid,
202 bmdata->fbid, -bmdata->xoffset, -bmdata->yoffset, output_ids,
203 output_count, gfxdata->selectedmode);
205 UNLOCK_BITMAP
207 if (ret) return FALSE; else return TRUE;
210 BOOL HIDDNouveauSwitchToVideoMode(OOP_Object * bm)
212 OOP_Class * cl = OOP_OCLASS(bm);
213 struct HIDDNouveauBitMapData * bmdata = OOP_INST_DATA(cl, bm);
214 OOP_Object * gfx = NULL;
215 struct HIDDNouveauData * gfxdata = NULL;
216 struct CardData * carddata = &(SD(cl)->carddata);
217 struct nouveau_device_priv *nvdev = nouveau_device(carddata->dev);
218 LONG i;
219 drmModeConnectorPtr selectedconnector = NULL;
220 HIDDT_ModeID modeid;
221 OOP_Object * sync;
222 OOP_Object * pf;
223 IPTR pixel, e;
224 IPTR hdisp, vdisp, hstart, hend, htotal, vstart, vend, vtotal;
225 LONG ret;
228 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
229 gfx = (OOP_Object *)e;
230 gfxdata = OOP_INST_DATA(OOP_OCLASS(gfx), gfx);
231 selectedconnector = (drmModeConnectorPtr)gfxdata->selectedconnector;
233 D(bug("[Nouveau] HIDDNouveauSwitchToVideoMode, bm: 0x%x\n", bm));
235 /* We should be able to get modeID from the bitmap */
236 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
238 if (modeid == vHidd_ModeID_Invalid)
240 D(bug("[Nouveau] Invalid ModeID\n"));
241 return FALSE;
244 /* Get Sync and PixelFormat properties */
245 struct pHidd_Gfx_GetMode __getmodemsg =
247 modeID: modeid,
248 syncPtr: &sync,
249 pixFmtPtr: &pf,
250 }, *getmodemsg = &__getmodemsg;
252 getmodemsg->mID = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_GetMode);
253 OOP_DoMethod(gfx, (OOP_Msg)getmodemsg);
255 OOP_GetAttr(sync, aHidd_Sync_PixelClock, &pixel);
256 OOP_GetAttr(sync, aHidd_Sync_HDisp, &hdisp);
257 OOP_GetAttr(sync, aHidd_Sync_VDisp, &vdisp);
258 OOP_GetAttr(sync, aHidd_Sync_HSyncStart, &hstart);
259 OOP_GetAttr(sync, aHidd_Sync_VSyncStart, &vstart);
260 OOP_GetAttr(sync, aHidd_Sync_HSyncEnd, &hend);
261 OOP_GetAttr(sync, aHidd_Sync_VSyncEnd, &vend);
262 OOP_GetAttr(sync, aHidd_Sync_HTotal, &htotal);
263 OOP_GetAttr(sync, aHidd_Sync_VTotal, &vtotal);
265 D(bug("[Nouveau] Sync: %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
266 pixel, hdisp, hstart, hend, htotal, vdisp, vstart, vend, vtotal));
268 D(bug("[Nouveau] Connector %d, CRTC %d\n",
269 selectedconnector->connector_id, gfxdata->selectedcrtcid));
271 /* Select mode */
272 gfxdata->selectedmode = NULL;
273 for (i = 0; i < selectedconnector->count_modes; i++)
275 drmModeModeInfoPtr mode = &selectedconnector->modes[i];
277 if ((mode->hdisplay == hdisp) && (mode->vdisplay == vdisp) &&
278 (mode->hsync_start == hstart) && (mode->vsync_start == vstart) &&
279 (mode->hsync_end == hend) && (mode->vsync_end == vend))
281 gfxdata->selectedmode = mode;
282 break;
286 if (!gfxdata->selectedmode)
288 D(bug("[Nouveau] Not able to select mode\n"));
289 return FALSE;
292 /* For screen switching the bitmap might have already once been a framebuffer
293 - check bmdata->fbid. Also the bitmap itself needs to know whether it is
294 added as framebuffer so that it can unregister itself in Dispose */
296 /* Add as frame buffer */
297 if (bmdata->fbid == 0)
299 ret = drmModeAddFB(nvdev->fd, bmdata->width, bmdata->height,
300 bmdata->depth, bmdata->bytesperpixel * 8,
301 bmdata->pitch, bmdata->bo->handle, &bmdata->fbid);
302 if (ret)
304 D(bug("[Nouveau] Not able to add framebuffer\n"));
305 return FALSE;
310 /* Switch mode */
311 if (!HIDDNouveauShowBitmapForSelectedMode(bm))
313 D(bug("[Nouveau] Not able to set crtc\n"));
314 return FALSE;
317 HIDDNouveauShowCursor(gfx, TRUE);
319 return TRUE;
322 /* PUBLIC METHODS */
323 OOP_Object * METHOD(Nouveau, Root, New)
325 drmModeCrtcPtr selectedcrtc = NULL;
326 drmModeConnectorPtr selectedconnector = NULL;
327 struct nouveau_device * dev = NULL;
328 struct nouveau_device_priv * nvdev = NULL;
329 struct TagItem * syncs = NULL;
330 struct CardData * carddata = &(SD(cl)->carddata);
331 LONG ret;
332 ULONG selectedcrtcid;
334 if (nouveau_init() < 0)
335 return NULL;
337 nouveau_device_open(&dev, "");
338 nvdev = nouveau_device(dev);
340 /* Select crtc and connector */
341 if (!HIDDNouveauSelectConnectorCrtc(nvdev->fd, &selectedconnector, &selectedcrtc))
343 D(bug("[Nouveau] Not able to select connector and crtc\n"));
344 return NULL;
347 selectedcrtcid = selectedcrtc->crtc_id;
348 drmModeFreeCrtc(selectedcrtc);
350 /* Read connector and build sync tags */
351 syncs = HIDDNouveauCreateSyncTagsFromConnector(cl, selectedconnector);
352 if (syncs == NULL)
354 D(bug("[Nouveau] Not able to read any sync modes\n"));
355 return NULL;
359 /* Call super contructor */
361 struct TagItem pftags_24bpp[] = {
362 { aHidd_PixFmt_RedShift, 8 }, /* 0 */
363 { aHidd_PixFmt_GreenShift, 16 }, /* 1 */
364 { aHidd_PixFmt_BlueShift, 24 }, /* 2 */
365 { aHidd_PixFmt_AlphaShift, 0 }, /* 3 */
366 { aHidd_PixFmt_RedMask, 0x00ff0000 }, /* 4 */
367 { aHidd_PixFmt_GreenMask, 0x0000ff00 }, /* 5 */
368 { aHidd_PixFmt_BlueMask, 0x000000ff }, /* 6 */
369 { aHidd_PixFmt_AlphaMask, 0x00000000 }, /* 7 */
370 { aHidd_PixFmt_ColorModel, vHidd_ColorModel_TrueColor }, /* 8 */
371 { aHidd_PixFmt_Depth, 24 }, /* 9 */
372 { aHidd_PixFmt_BytesPerPixel, 4 }, /* 10 */
373 { aHidd_PixFmt_BitsPerPixel, 24 }, /* 11 */
374 { aHidd_PixFmt_StdPixFmt, vHidd_StdPixFmt_BGR032 }, /* 12 Native */
375 { aHidd_PixFmt_BitMapType, vHidd_BitMapType_Chunky }, /* 15 */
376 { TAG_DONE, 0UL }
379 struct TagItem pftags_16bpp[] = {
380 { aHidd_PixFmt_RedShift, 16 }, /* 0 */
381 { aHidd_PixFmt_GreenShift, 21 }, /* 1 */
382 { aHidd_PixFmt_BlueShift, 27 }, /* 2 */
383 { aHidd_PixFmt_AlphaShift, 0 }, /* 3 */
384 { aHidd_PixFmt_RedMask, 0x0000f800 }, /* 4 */
385 { aHidd_PixFmt_GreenMask, 0x000007e0 }, /* 5 */
386 { aHidd_PixFmt_BlueMask, 0x0000001f }, /* 6 */
387 { aHidd_PixFmt_AlphaMask, 0x00000000 }, /* 7 */
388 { aHidd_PixFmt_ColorModel, vHidd_ColorModel_TrueColor }, /* 8 */
389 { aHidd_PixFmt_Depth, 16 }, /* 9 */
390 { aHidd_PixFmt_BytesPerPixel, 2 }, /* 10 */
391 { aHidd_PixFmt_BitsPerPixel, 16 }, /* 11 */
392 { aHidd_PixFmt_StdPixFmt, vHidd_StdPixFmt_RGB16_LE }, /* 12 */
393 { aHidd_PixFmt_BitMapType, vHidd_BitMapType_Chunky }, /* 15 */
394 { TAG_DONE, 0UL }
397 struct TagItem modetags[] = {
398 { aHidd_Gfx_PixFmtTags, (IPTR)pftags_24bpp },
399 { aHidd_Gfx_PixFmtTags, (IPTR)pftags_16bpp },
400 { TAG_MORE, (IPTR)syncs }, /* FIXME: sync tags will leak */
401 { TAG_DONE, 0UL }
404 struct TagItem mytags[] = {
405 { aHidd_Gfx_ModeTags, (IPTR)modetags },
406 { TAG_MORE, (IPTR)msg->attrList }
409 struct pRoot_New mymsg;
411 mymsg.mID = msg->mID;
412 mymsg.attrList = mytags;
414 msg = &mymsg;
417 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
419 D(bug("[Nouveau] GFX New\n"));
421 if (o)
423 struct HIDDNouveauData * gfxdata = OOP_INST_DATA(cl, o);
424 /* Pass local information to class */
425 gfxdata->selectedcrtcid = selectedcrtcid;
426 gfxdata->selectedmode = NULL;
427 gfxdata->selectedconnector = selectedconnector;
428 carddata->dev = dev;
429 ULONG gartsize = 0;
430 UQUAD value;
432 /* Check chipset architecture */
433 switch (carddata->dev->chipset & 0xf0)
435 case 0x00:
436 carddata->architecture = NV_ARCH_04;
437 break;
438 case 0x10:
439 carddata->architecture = NV_ARCH_10;
440 break;
441 case 0x20:
442 carddata->architecture = NV_ARCH_20;
443 break;
444 case 0x30:
445 carddata->architecture = NV_ARCH_30;
446 break;
447 case 0x40:
448 case 0x60:
449 carddata->architecture = NV_ARCH_40;
450 break;
451 case 0x50:
452 case 0x80:
453 case 0x90:
454 case 0xa0:
455 carddata->architecture = NV_ARCH_50;
456 break;
457 case 0xc0:
458 carddata->architecture = NV_ARCH_C0;
459 break;
460 default:
461 /* TODO: report error, how to handle it? */
462 return NULL;
465 nouveau_device_get_param(carddata->dev, NOUVEAU_GETPARAM_BUS_TYPE, &value);
466 if (value == NV_PCIE)
467 carddata->IsPCIE = TRUE;
468 else
469 carddata->IsPCIE = FALSE;
471 /* Allocate dma channel */
472 ret = nouveau_channel_alloc(carddata->dev, NvDmaFB, NvDmaTT,
473 24 * 1024, &carddata->chan);
474 if (ret < 0)
476 /* TODO: Check ret, how to handle ? */
479 /* Initialize acceleration objects */
481 ret = HIDDNouveauAccelCommonInit(carddata);
482 if (ret < 0)
484 /* TODO: Check ret, how to handle ? */
487 /* Allocate buffer object for cursor */
488 nouveau_bo_new(carddata->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP,
489 0, 64 * 64 * 4, &gfxdata->cursor);
490 /* TODO: Check return, hot to handle */
492 /* Allocate GART scratch buffer */
493 if (carddata->dev->vm_gart_size > GART_BUFFER_SIZE)
494 gartsize = GART_BUFFER_SIZE;
495 else
496 /* always leave 512kb for other things like the fifos */
497 gartsize = carddata->dev->vm_gart_size - 512 * 1024;
499 /* This can fail */
500 nouveau_bo_new(carddata->dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
501 0, gartsize, &carddata->GART);
502 InitSemaphore(&carddata->gartsemaphore);
504 /* Set initial pattern (else 16-bit ROPs are not working) */
505 switch(carddata->architecture)
507 case(NV_ARCH_03):
508 case(NV_ARCH_04):
509 case(NV_ARCH_10):
510 case(NV_ARCH_20):
511 case(NV_ARCH_30):
512 case(NV_ARCH_40):
513 HIDDNouveauNV04SetPattern(carddata, ~0, ~0, ~0, ~0);
514 break;
515 case(NV_ARCH_50):
516 HIDDNouveauNV50SetPattern(carddata, ~0, ~0, ~0, ~0);
517 break;
518 case(NV_ARCH_C0):
519 HIDDNouveauNVC0SetPattern(carddata, ~0, ~0, ~0, ~0);
520 break;
523 /* Create compositor object */
525 struct TagItem comptags [] =
527 { aHidd_Compositor_GfxHidd, (IPTR)o },
528 { TAG_DONE, TAG_DONE }
530 gfxdata->compositor = OOP_NewObject(SD(cl)->compositorclass, NULL, comptags);
531 /* TODO: Check if object was created, how to handle ? */
536 return o;
539 return NULL;
542 /* FIXME: IMPLEMENT DISPOSE - calling nouveau_close(), freeing cursor bo, gart bo,
543 selectedconnector, gfxdata->compositor, HIDDNouveauAccelFree */
545 /* FIXME: IMPLEMENT DISPOSE BITMAP - REMOVE FROM FB IF MARKED AS SUCH */
547 OOP_Object * METHOD(Nouveau, Hidd_Gfx, CreateObject)
549 struct HIDDNouveauData * gfxdata = OOP_INST_DATA(cl, o);
550 OOP_Object *object = NULL;
552 if (msg->cl == SD(cl)->basebm)
554 struct pHidd_Gfx_CreateObject mymsg;
555 HIDDT_ModeID modeid;
556 HIDDT_StdPixFmt stdpf;
558 struct TagItem mytags [] =
560 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_ClassPtr */
561 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_Align */
562 { aHidd_BitMap_Nouveau_CompositorHidd, (IPTR)gfxdata->compositor },
563 { TAG_MORE, (IPTR)msg->attrList }
566 /* Check if user provided valid ModeID */
567 /* Check for framebuffer - not needed as Nouveau is a NoFramebuffer driver */
568 /* Check for displayable - not needed - displayable has ModeID and we don't
569 distinguish between on-screen and off-screen bitmaps */
570 modeid = (HIDDT_ModeID)GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
571 if (vHidd_ModeID_Invalid != modeid)
573 /* User supplied a valid modeid. We can use our bitmap class */
574 mytags[0].ti_Tag = aHidd_BitMap_ClassPtr;
575 mytags[0].ti_Data = (IPTR)SD(cl)->bmclass;
578 /* Check if bitmap is a planar bitmap */
579 stdpf = (HIDDT_StdPixFmt)GetTagData(aHidd_BitMap_StdPixFmt, vHidd_StdPixFmt_Unknown, msg->attrList);
580 if (vHidd_StdPixFmt_Plane == stdpf)
582 mytags[1].ti_Tag = aHidd_BitMap_Align;
583 mytags[1].ti_Data = 32;
586 /* We init a new message struct */
587 mymsg.mID = msg->mID;
588 mymsg.cl = msg->cl;
589 mymsg.attrList = mytags;
591 /* Pass the new message to the superclass */
592 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&mymsg);
594 else if (SD(cl)->basegallium && (msg->cl == SD(cl)->basegallium))
596 object = OOP_NewObject(NULL, CLID_Hidd_Gallium_Nouveau, msg->attrList);
598 else
599 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
601 return object;
604 VOID METHOD(Nouveau, Hidd_Gfx, CopyBox)
606 OOP_Class * srcclass = OOP_OCLASS(msg->src);
607 OOP_Class * destclass = OOP_OCLASS(msg->dest);
609 if (IS_NOUVEAU_BM_CLASS(srcclass) && IS_NOUVEAU_BM_CLASS(destclass))
611 /* FIXME: add checks for pixel format, etc */
612 struct HIDDNouveauBitMapData * srcdata = OOP_INST_DATA(srcclass, msg->src);
613 struct HIDDNouveauBitMapData * destdata = OOP_INST_DATA(destclass, msg->dest);
614 struct CardData * carddata = &(SD(cl)->carddata);
615 BOOL ret = FALSE;
617 D(bug("[Nouveau] CopyBox 0x%x -> 0x%x\n", msg->src, msg->dest));
619 LOCK_MULTI_BITMAP
620 LOCK_BITMAP_BM(srcdata)
621 LOCK_BITMAP_BM(destdata)
622 UNLOCK_MULTI_BITMAP
623 UNMAP_BUFFER_BM(srcdata)
624 UNMAP_BUFFER_BM(destdata)
626 switch(carddata->architecture)
628 case(NV_ARCH_03):
629 case(NV_ARCH_04):
630 case(NV_ARCH_10):
631 case(NV_ARCH_20):
632 case(NV_ARCH_30):
633 case(NV_ARCH_40):
634 ret = HIDDNouveauNV04CopySameFormat(carddata, srcdata, destdata,
635 msg->srcX, msg->srcY, msg->destX, msg->destY,
636 msg->width, msg->height, GC_DRMD(msg->gc));
637 break;
638 case(NV_ARCH_50):
639 ret = HIDDNouveauNV50CopySameFormat(carddata, srcdata, destdata,
640 msg->srcX, msg->srcY, msg->destX, msg->destY,
641 msg->width, msg->height, GC_DRMD(msg->gc));
642 break;
643 case(NV_ARCH_C0):
644 ret = HIDDNouveauNVC0CopySameFormat(carddata, srcdata, destdata,
645 msg->srcX, msg->srcY, msg->destX, msg->destY,
646 msg->width, msg->height, GC_DRMD(msg->gc));
647 break;
650 UNLOCK_BITMAP_BM(destdata);
651 UNLOCK_BITMAP_BM(srcdata);
653 if (ret)
654 return;
656 /* If operation failed, fallback to default method */
659 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
663 VOID METHOD(Nouveau, Root, Get)
665 ULONG idx;
667 if (IS_GFX_ATTR(msg->attrID, idx))
669 switch (idx)
671 case aoHidd_Gfx_NoFrameBuffer:
672 *msg->storage = (IPTR)TRUE;
673 return;
674 case aoHidd_Gfx_SupportsHWCursor:
675 *msg->storage = (IPTR)TRUE;
676 return;
677 case aoHidd_Gfx_HWSpriteTypes:
678 *msg->storage = vHidd_SpriteType_DirectColor;
679 return;
680 case aoHidd_Gfx_DriverName:
681 *msg->storage = (IPTR)"Nouveau";
682 return;
686 if (IS_GFXNOUVEAU_ATTR(msg->attrID, idx))
688 switch(idx)
690 case(aoHidd_Gfx_Nouveau_VRAMSize):
692 UQUAD value;
693 nouveau_device_get_param(SD(cl)->carddata.dev, NOUVEAU_GETPARAM_VRAM_SIZE, &value);
694 *msg->storage = (IPTR)value;
695 return;
697 case(aoHidd_Gfx_Nouveau_GARTSize):
699 UQUAD value;
700 nouveau_device_get_param(SD(cl)->carddata.dev, NOUVEAU_GETPARAM_GART_SIZE, &value);
701 *msg->storage = (IPTR)value;
702 return;
704 case(aoHidd_Gfx_Nouveau_VRAMFree):
706 UQUAD value;
707 nouveau_device_get_param(SD(cl)->carddata.dev, NOUVEAU_GETPARAM_VRAM_FREE, &value);
708 *msg->storage = (IPTR)value;
709 return;
711 case(aoHidd_Gfx_Nouveau_GARTFree):
713 UQUAD value;
714 nouveau_device_get_param(SD(cl)->carddata.dev, NOUVEAU_GETPARAM_GART_FREE, &value);
715 *msg->storage = (IPTR)value;
716 return;
721 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
724 ULONG METHOD(Nouveau, Hidd_Gfx, ShowViewPorts)
726 struct HIDDNouveauData * gfxdata = OOP_INST_DATA(cl, o);
727 struct pHidd_Compositor_BitMapStackChanged bscmsg =
729 mID : OOP_GetMethodID(IID_Hidd_Compositor, moHidd_Compositor_BitMapStackChanged),
730 data : msg->Data
733 D(bug("[Nouveau] ShowViewPorts enter TopLevelBM %x\n", (msg->Data ? (msg->Data->Bitmap) : NULL)));
735 OOP_DoMethod(gfxdata->compositor, (OOP_Msg)&bscmsg);
737 return TRUE; /* Indicate driver supports this method */
740 #if AROS_BIG_ENDIAN
741 #define Machine_ARGB32 vHidd_StdPixFmt_ARGB32
742 #else
743 #define Machine_ARGB32 vHidd_StdPixFmt_BGRA32
744 #endif
746 BOOL METHOD(Nouveau, Hidd_Gfx, SetCursorShape)
748 struct HIDDNouveauData * gfxdata = OOP_INST_DATA(cl, o);
750 if (msg->shape == NULL)
752 /* Hide cursor */
753 HIDDNouveauShowCursor(o, FALSE);
755 else
757 IPTR width, height;
758 ULONG i;
759 ULONG x, y;
760 ULONG curimage[64 * 64];
761 struct CardData * carddata = &(SD(cl)->carddata);
763 OOP_GetAttr(msg->shape, aHidd_BitMap_Width, &width);
764 OOP_GetAttr(msg->shape, aHidd_BitMap_Height, &height);
767 if (width > 64) width = 64;
768 if (height > 64) height = 64;
770 /* Map the cursor buffer */
771 nouveau_bo_map(gfxdata->cursor, NOUVEAU_BO_WR);
773 /* Clear the matrix */
774 for (i = 0; i < 64 * 64; i++)
775 ((ULONG*)gfxdata->cursor->map)[i] = 0;
777 /* Get data from the bitmap */
778 HIDD_BM_GetImage(msg->shape, (UBYTE *)curimage, 64 * 4, 0, 0,
779 width, height, Machine_ARGB32);
781 if (carddata->architecture < NV_ARCH_50)
783 ULONG offset, pixel, blue, green, red, alpha;
785 /* The image needs to be premultiplied */
786 for (y = 0; y < height; y++)
787 for (x = 0; x < width; x++)
789 offset = y * 64 + x;
790 pixel = curimage[offset];
791 blue = (pixel & 0x000000FF);
792 green = (pixel & 0x0000FF00) >> 8;
793 red = (pixel & 0x00FF0000) >> 16;
794 alpha = (pixel & 0xFF000000) >> 24;
796 blue = (blue * alpha) / 255;
797 green = (green * alpha) / 255;
798 red = (red * alpha) / 255;
800 curimage[offset] = (alpha << 24) | (red << 16) | (green << 8) | blue;
804 for (y = 0; y < height; y++)
805 for (x = 0; x < width; x++)
807 ULONG offset = y * 64 + x;
808 writel(curimage[offset], ((ULONG *)gfxdata->cursor->map) + (offset));
811 nouveau_bo_unmap(gfxdata->cursor);
813 /* Show updated cursor */
814 HIDDNouveauShowCursor(o, TRUE);
817 return TRUE;
820 BOOL METHOD(Nouveau, Hidd_Gfx, SetCursorPos)
822 struct HIDDNouveauData * gfxdata = OOP_INST_DATA(cl, o);
823 struct CardData * carddata = &(SD(cl)->carddata);
824 struct nouveau_device_priv * nvdev = nouveau_device(carddata->dev);
826 drmModeMoveCursor(nvdev->fd, gfxdata->selectedcrtcid, msg->x, msg->y);
828 return TRUE;
831 VOID METHOD(Nouveau, Hidd_Gfx, SetCursorVisible)
833 HIDDNouveauShowCursor(o, msg->visible);
836 static struct HIDD_ModeProperties modeprops =
838 DIPF_IS_SPRITES,
840 COMPF_ABOVE
843 ULONG METHOD(Nouveau, Hidd_Gfx, ModeProperties)
845 ULONG len = msg->propsLen;
847 if (len > sizeof(modeprops))
848 len = sizeof(modeprops);
849 CopyMem(&modeprops, msg->props, len);
851 return len;