2 Copyright © 2010-2017, The AROS Development Team. All rights reserved.
6 #include "nouveau_intern.h"
7 #include "compositor.h"
9 #include <graphics/displayinfo.h>
10 #include <proto/utility.h>
11 #include <nouveau_drm.h>
14 #include <aros/debug.h>
15 #include <proto/oop.h>
17 #include "arosdrmmode.h"
20 #undef HiddPixFmtAttrBase
21 #undef HiddGfxAttrBase
22 #undef HiddGfxNouveauAttrBase
23 #undef HiddSyncAttrBase
24 #undef HiddBitMapAttrBase
25 #undef HiddCompositorAttrBase
26 #undef HiddBitMapNouveauAttrBase
28 #define HiddAttrBase (SD(cl)->hiddAttrBase)
29 #define HiddPixFmtAttrBase (SD(cl)->pixFmtAttrBase)
30 #define HiddGfxAttrBase (SD(cl)->gfxAttrBase)
31 #define HiddGfxNouveauAttrBase (SD(cl)->gfxNouveauAttrBase)
32 #define HiddSyncAttrBase (SD(cl)->syncAttrBase)
33 #define HiddBitMapAttrBase (SD(cl)->bitMapAttrBase)
34 #define HiddCompositorAttrBase (SD(cl)->compositorAttrBase)
35 #define HiddBitMapNouveauAttrBase (SD(cl)->bitMapNouveauAttrBase)
37 #define MAX_BITMAP_WIDTH 4096
38 #define MAX_BITMAP_HEIGHT 4096
39 #define GART_BUFFER_SIZE (12 * 1024 * 1024)
41 /* HELPER FUNCTIONS */
42 VOID
HIDDNouveauShowCursor(OOP_Object
* gfx
, BOOL visible
)
44 OOP_Class
* cl
= OOP_OCLASS(gfx
);
45 struct HIDDNouveauData
* gfxdata
= OOP_INST_DATA(cl
, gfx
);
46 struct CardData
* carddata
= &(SD(cl
)->carddata
);
47 struct nouveau_device_priv
* nvdev
= nouveau_device(carddata
->dev
);
53 drmModeSetCursor(nvdev
->fd
, gfxdata
->selectedcrtcid
,
54 gfxdata
->cursor
->handle
, 64, 64);
58 drmModeSetCursor(nvdev
->fd
, gfxdata
->selectedcrtcid
,
65 static BOOL
HIDDNouveauSelectConnectorCrtc(LONG fd
, drmModeConnectorPtr
* selectedconnector
,
66 drmModeCrtcPtr
* selectedcrtc
)
68 *selectedconnector
= NULL
;
70 drmModeResPtr drmmode
= NULL
;
71 LONG i
; ULONG crtc_id
;
75 /* Get all components information */
76 drmmode
= drmModeGetResources(fd
);
79 D(bug("[Nouveau] Not able to get resources information\n"));
84 /* Selecting connector */
85 for (i
= 0; i
< drmmode
->count_connectors
; i
++)
87 drmModeConnectorPtr connector
= drmModeGetConnector(fd
, drmmode
->connectors
[i
]);
91 if (connector
->connection
== DRM_MODE_CONNECTED
)
93 /* Found connected connector */
94 *selectedconnector
= connector
;
98 drmModeFreeConnector(connector
);
102 if (!(*selectedconnector
))
104 D(bug("[Nouveau] No connected connector\n"));
105 drmModeFreeResources(drmmode
);
110 /* Selecting first available CRTC */
111 if (drmmode
->count_crtcs
> 0)
112 crtc_id
= drmmode
->crtcs
[0];
116 *selectedcrtc
= drmModeGetCrtc(fd
, crtc_id
);
117 if (!(*selectedcrtc
))
119 D(bug("[Nouveau] Not able to get crtc information for crtc_id %d\n", crtc_id
));
120 drmModeFreeConnector(*selectedconnector
);
121 *selectedconnector
= NULL
;
122 drmModeFreeResources(drmmode
);
127 drmModeFreeResources(drmmode
);
134 static struct TagItem
* HIDDNouveauCreateSyncTagsFromConnector(OOP_Class
* cl
, drmModeConnectorPtr connector
)
136 struct TagItem
* syncs
= NULL
;
137 ULONG modescount
= connector
->count_modes
;
143 /* Allocate enough structures */
144 syncs
= HIDDNouveauAlloc(sizeof(struct TagItem
) * modescount
);
146 for (i
= 0; i
< modescount
; i
++)
148 struct TagItem
* sync
= HIDDNouveauAlloc(sizeof(struct TagItem
) * 15);
151 drmModeModeInfoPtr mode
= &connector
->modes
[i
];
153 sync
[j
].ti_Tag
= aHidd_Sync_PixelClock
; sync
[j
++].ti_Data
= mode
->clock
;
155 sync
[j
].ti_Tag
= aHidd_Sync_HDisp
; sync
[j
++].ti_Data
= mode
->hdisplay
;
156 sync
[j
].ti_Tag
= aHidd_Sync_HSyncStart
; sync
[j
++].ti_Data
= mode
->hsync_start
;
157 sync
[j
].ti_Tag
= aHidd_Sync_HSyncEnd
; sync
[j
++].ti_Data
= mode
->hsync_end
;
158 sync
[j
].ti_Tag
= aHidd_Sync_HTotal
; sync
[j
++].ti_Data
= mode
->htotal
;
159 sync
[j
].ti_Tag
= aHidd_Sync_HMin
; sync
[j
++].ti_Data
= mode
->hdisplay
;
160 sync
[j
].ti_Tag
= aHidd_Sync_HMax
; sync
[j
++].ti_Data
= MAX_BITMAP_WIDTH
;
162 sync
[j
].ti_Tag
= aHidd_Sync_VDisp
; sync
[j
++].ti_Data
= mode
->vdisplay
;
163 sync
[j
].ti_Tag
= aHidd_Sync_VSyncStart
; sync
[j
++].ti_Data
= mode
->vsync_start
;
164 sync
[j
].ti_Tag
= aHidd_Sync_VSyncEnd
; sync
[j
++].ti_Data
= mode
->vsync_end
;
165 sync
[j
].ti_Tag
= aHidd_Sync_VTotal
; sync
[j
++].ti_Data
= mode
->vtotal
;
166 sync
[j
].ti_Tag
= aHidd_Sync_VMin
; sync
[j
++].ti_Data
= mode
->vdisplay
;
167 sync
[j
].ti_Tag
= aHidd_Sync_VMax
; sync
[j
++].ti_Data
= MAX_BITMAP_HEIGHT
;
170 STRPTR syncname
= HIDDNouveauAlloc(32);
171 sprintf(syncname
, "NV:%dx%d@%d", mode
->hdisplay
, mode
->vdisplay
, mode
->vrefresh
);
173 sync
[j
].ti_Tag
= aHidd_Sync_Description
; sync
[j
++].ti_Data
= (IPTR
)syncname
;
175 sync
[j
].ti_Tag
= TAG_DONE
; sync
[j
++].ti_Data
= 0UL;
177 syncs
[i
].ti_Tag
= aHidd_Gfx_SyncTags
;
178 syncs
[i
].ti_Data
= (IPTR
)sync
;
184 /* This function assumes that the mode, crtc and output are already selected */
185 static BOOL
HIDDNouveauShowBitmapForSelectedMode(OOP_Object
* bm
)
187 OOP_Class
* cl
= OOP_OCLASS(bm
);
188 struct HIDDNouveauData
* gfxdata
= NULL
;
189 struct HIDDNouveauBitMapData
* bmdata
= OOP_INST_DATA(cl
, bm
);
190 struct CardData
* carddata
= &(SD(cl
)->carddata
);
191 struct nouveau_device_priv
*nvdev
= nouveau_device(carddata
->dev
);
192 uint32_t output_ids
[] = {0};
193 uint32_t output_count
= 1;
195 OOP_Object
* gfx
= NULL
;
201 /* Check if passed bitmap has been registered as framebuffer */
202 if (bmdata
->fbid
== 0)
209 OOP_GetAttr(bm
, aHidd_BitMap_GfxHidd
, &e
);
210 gfx
= (OOP_Object
*)e
;
211 gfxdata
= OOP_INST_DATA(OOP_OCLASS(gfx
), gfx
);
212 output_ids
[0] = ((drmModeConnectorPtr
)gfxdata
->selectedconnector
)->connector_id
;
215 ret
= drmModeSetCrtc(nvdev
->fd
, gfxdata
->selectedcrtcid
,
216 bmdata
->fbid
, -bmdata
->xoffset
, -bmdata
->yoffset
, output_ids
,
217 output_count
, gfxdata
->selectedmode
);
222 if (ret
) return FALSE
; else return TRUE
;
225 BOOL
HIDDNouveauSwitchToVideoMode(OOP_Object
* bm
)
227 OOP_Class
* cl
= OOP_OCLASS(bm
);
228 struct HIDDNouveauBitMapData
* bmdata
= OOP_INST_DATA(cl
, bm
);
229 OOP_Object
* gfx
= NULL
;
230 struct HIDDNouveauData
* gfxdata
= NULL
;
231 struct CardData
* carddata
= &(SD(cl
)->carddata
);
232 struct nouveau_device_priv
*nvdev
= nouveau_device(carddata
->dev
);
234 drmModeConnectorPtr selectedconnector
= NULL
;
239 IPTR hdisp
, vdisp
, hstart
, hend
, htotal
, vstart
, vend
, vtotal
;
244 OOP_GetAttr(bm
, aHidd_BitMap_GfxHidd
, &e
);
245 gfx
= (OOP_Object
*)e
;
246 gfxdata
= OOP_INST_DATA(OOP_OCLASS(gfx
), gfx
);
247 selectedconnector
= (drmModeConnectorPtr
)gfxdata
->selectedconnector
;
249 D(bug("[Nouveau] HIDDNouveauSwitchToVideoMode, bm: 0x%x\n", bm
));
251 /* We should be able to get modeID from the bitmap */
252 OOP_GetAttr(bm
, aHidd_BitMap_ModeID
, &modeid
);
254 if (modeid
== vHidd_ModeID_Invalid
)
256 D(bug("[Nouveau] Invalid ModeID\n"));
261 /* Get Sync and PixelFormat properties */
262 struct pHidd_Gfx_GetMode __getmodemsg
=
267 }, *getmodemsg
= &__getmodemsg
;
269 getmodemsg
->mID
= OOP_GetMethodID(IID_Hidd_Gfx
, moHidd_Gfx_GetMode
);
270 OOP_DoMethod(gfx
, (OOP_Msg
)getmodemsg
);
272 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &pixel
);
273 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &hdisp
);
274 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &vdisp
);
275 OOP_GetAttr(sync
, aHidd_Sync_HSyncStart
, &hstart
);
276 OOP_GetAttr(sync
, aHidd_Sync_VSyncStart
, &vstart
);
277 OOP_GetAttr(sync
, aHidd_Sync_HSyncEnd
, &hend
);
278 OOP_GetAttr(sync
, aHidd_Sync_VSyncEnd
, &vend
);
279 OOP_GetAttr(sync
, aHidd_Sync_HTotal
, &htotal
);
280 OOP_GetAttr(sync
, aHidd_Sync_VTotal
, &vtotal
);
282 D(bug("[Nouveau] Sync: %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
283 pixel
, hdisp
, hstart
, hend
, htotal
, vdisp
, vstart
, vend
, vtotal
));
285 D(bug("[Nouveau] Connector %d, CRTC %d\n",
286 selectedconnector
->connector_id
, gfxdata
->selectedcrtcid
));
289 gfxdata
->selectedmode
= NULL
;
290 for (i
= 0; i
< selectedconnector
->count_modes
; i
++)
292 drmModeModeInfoPtr mode
= &selectedconnector
->modes
[i
];
294 if ((mode
->hdisplay
== hdisp
) && (mode
->vdisplay
== vdisp
) &&
295 (mode
->hsync_start
== hstart
) && (mode
->vsync_start
== vstart
) &&
296 (mode
->hsync_end
== hend
) && (mode
->vsync_end
== vend
))
298 gfxdata
->selectedmode
= mode
;
303 if (!gfxdata
->selectedmode
)
305 D(bug("[Nouveau] Not able to select mode\n"));
310 /* For screen switching the bitmap might have already once been a framebuffer
311 - check bmdata->fbid. Also the bitmap itself needs to know whether it is
312 added as framebuffer so that it can unregister itself in Dispose */
314 /* Add as frame buffer */
315 if (bmdata
->fbid
== 0)
317 ret
= drmModeAddFB(nvdev
->fd
, bmdata
->width
, bmdata
->height
,
318 bmdata
->depth
, bmdata
->bytesperpixel
* 8,
319 bmdata
->pitch
, bmdata
->bo
->handle
, &bmdata
->fbid
);
322 D(bug("[Nouveau] Not able to add framebuffer\n"));
330 if (!HIDDNouveauShowBitmapForSelectedMode(bm
))
332 D(bug("[Nouveau] Not able to set crtc\n"));
337 HIDDNouveauShowCursor(gfx
, TRUE
);
344 OOP_Object
* METHOD(Nouveau
, Root
, New
)
346 drmModeCrtcPtr selectedcrtc
= NULL
;
347 drmModeConnectorPtr selectedconnector
= NULL
;
348 struct nouveau_device
* dev
= NULL
;
349 struct nouveau_device_priv
* nvdev
= NULL
;
350 struct TagItem
* syncs
= NULL
;
351 struct CardData
* carddata
= &(SD(cl
)->carddata
);
353 ULONG selectedcrtcid
;
355 if (nouveau_init() < 0)
360 nouveau_device_open(&dev
, "");
361 nvdev
= nouveau_device(dev
);
363 /* Select crtc and connector */
364 if (!HIDDNouveauSelectConnectorCrtc(nvdev
->fd
, &selectedconnector
, &selectedcrtc
))
366 D(bug("[Nouveau] Not able to select connector and crtc\n"));
373 selectedcrtcid
= selectedcrtc
->crtc_id
;
374 drmModeFreeCrtc(selectedcrtc
);
376 /* Read connector and build sync tags */
377 syncs
= HIDDNouveauCreateSyncTagsFromConnector(cl
, selectedconnector
);
380 D(bug("[Nouveau] Not able to read any sync modes\n"));
386 /* Call super contructor */
388 struct TagItem pftags_24bpp
[] = {
389 { aHidd_PixFmt_RedShift
, 8 }, /* 0 */
390 { aHidd_PixFmt_GreenShift
, 16 }, /* 1 */
391 { aHidd_PixFmt_BlueShift
, 24 }, /* 2 */
392 { aHidd_PixFmt_AlphaShift
, 0 }, /* 3 */
393 { aHidd_PixFmt_RedMask
, 0x00ff0000 }, /* 4 */
394 { aHidd_PixFmt_GreenMask
, 0x0000ff00 }, /* 5 */
395 { aHidd_PixFmt_BlueMask
, 0x000000ff }, /* 6 */
396 { aHidd_PixFmt_AlphaMask
, 0x00000000 }, /* 7 */
397 { aHidd_PixFmt_ColorModel
, vHidd_ColorModel_TrueColor
}, /* 8 */
398 { aHidd_PixFmt_Depth
, 24 }, /* 9 */
399 { aHidd_PixFmt_BytesPerPixel
, 4 }, /* 10 */
400 { aHidd_PixFmt_BitsPerPixel
, 24 }, /* 11 */
401 { aHidd_PixFmt_StdPixFmt
, vHidd_StdPixFmt_BGR032
}, /* 12 Native */
402 { aHidd_PixFmt_BitMapType
, vHidd_BitMapType_Chunky
}, /* 15 */
406 struct TagItem pftags_16bpp
[] = {
407 { aHidd_PixFmt_RedShift
, 16 }, /* 0 */
408 { aHidd_PixFmt_GreenShift
, 21 }, /* 1 */
409 { aHidd_PixFmt_BlueShift
, 27 }, /* 2 */
410 { aHidd_PixFmt_AlphaShift
, 0 }, /* 3 */
411 { aHidd_PixFmt_RedMask
, 0x0000f800 }, /* 4 */
412 { aHidd_PixFmt_GreenMask
, 0x000007e0 }, /* 5 */
413 { aHidd_PixFmt_BlueMask
, 0x0000001f }, /* 6 */
414 { aHidd_PixFmt_AlphaMask
, 0x00000000 }, /* 7 */
415 { aHidd_PixFmt_ColorModel
, vHidd_ColorModel_TrueColor
}, /* 8 */
416 { aHidd_PixFmt_Depth
, 16 }, /* 9 */
417 { aHidd_PixFmt_BytesPerPixel
, 2 }, /* 10 */
418 { aHidd_PixFmt_BitsPerPixel
, 16 }, /* 11 */
419 { aHidd_PixFmt_StdPixFmt
, vHidd_StdPixFmt_RGB16_LE
}, /* 12 */
420 { aHidd_PixFmt_BitMapType
, vHidd_BitMapType_Chunky
}, /* 15 */
424 struct TagItem modetags
[] = {
425 { aHidd_Gfx_PixFmtTags
, (IPTR
)pftags_24bpp
},
426 { aHidd_Gfx_PixFmtTags
, (IPTR
)pftags_16bpp
},
427 { TAG_MORE
, (IPTR
)syncs
}, /* FIXME: sync tags will leak */
431 struct TagItem mytags
[] = {
432 { aHidd_Gfx_ModeTags
, (IPTR
)modetags
},
433 { aHidd_Name
, (IPTR
)"Nouveau" },
434 { aHidd_HardwareName
, (IPTR
)"Nvidia Gfx Adaptor" },
435 { aHidd_ProducerName
, (IPTR
)"Nvidia Corporation" },
436 { TAG_MORE
, (IPTR
)msg
->attrList
}
439 struct pRoot_New mymsg
;
441 mymsg
.mID
= msg
->mID
;
442 mymsg
.attrList
= mytags
;
447 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
449 D(bug("[Nouveau] GFX New\n"));
453 struct HIDDNouveauData
* gfxdata
= OOP_INST_DATA(cl
, o
);
454 /* Pass local information to class */
455 gfxdata
->selectedcrtcid
= selectedcrtcid
;
456 gfxdata
->selectedmode
= NULL
;
457 gfxdata
->selectedconnector
= selectedconnector
;
462 /* Check chipset architecture */
463 switch (carddata
->dev
->chipset
& 0xf0)
466 carddata
->architecture
= NV_ARCH_04
;
469 carddata
->architecture
= NV_ARCH_10
;
472 carddata
->architecture
= NV_ARCH_20
;
475 carddata
->architecture
= NV_ARCH_30
;
479 carddata
->architecture
= NV_ARCH_40
;
485 carddata
->architecture
= NV_ARCH_50
;
488 carddata
->architecture
= NV_ARCH_C0
;
491 /* TODO: report error, how to handle it? */
496 nouveau_device_get_param(carddata
->dev
, NOUVEAU_GETPARAM_BUS_TYPE
, &value
);
497 if (value
== NV_PCIE
)
498 carddata
->IsPCIE
= TRUE
;
500 carddata
->IsPCIE
= FALSE
;
502 /* Allocate dma channel */
503 ret
= nouveau_channel_alloc(carddata
->dev
, NvDmaFB
, NvDmaTT
,
504 24 * 1024, &carddata
->chan
);
507 /* TODO: Check ret, how to handle ? */
510 /* Initialize acceleration objects */
512 ret
= HIDDNouveauAccelCommonInit(carddata
);
515 /* TODO: Check ret, how to handle ? */
518 /* Allocate buffer object for cursor */
519 nouveau_bo_new(carddata
->dev
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_MAP
,
520 0, 64 * 64 * 4, &gfxdata
->cursor
);
521 /* TODO: Check return, hot to handle */
523 /* Allocate GART scratch buffer */
524 if (carddata
->dev
->vm_gart_size
> GART_BUFFER_SIZE
)
525 gartsize
= GART_BUFFER_SIZE
;
527 /* always leave 512kb for other things like the fifos */
528 gartsize
= carddata
->dev
->vm_gart_size
- 512 * 1024;
531 nouveau_bo_new(carddata
->dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
532 0, gartsize
, &carddata
->GART
);
533 InitSemaphore(&carddata
->gartsemaphore
);
535 /* Set initial pattern (else 16-bit ROPs are not working) */
536 switch(carddata
->architecture
)
544 HIDDNouveauNV04SetPattern(carddata
, ~0, ~0, ~0, ~0);
547 HIDDNouveauNV50SetPattern(carddata
, ~0, ~0, ~0, ~0);
550 HIDDNouveauNVC0SetPattern(carddata
, ~0, ~0, ~0, ~0);
554 /* Create compositor object */
556 struct TagItem comptags
[] =
558 { aHidd_Compositor_GfxHidd
, (IPTR
)o
},
559 { TAG_DONE
, TAG_DONE
}
561 gfxdata
->compositor
= OOP_NewObject(SD(cl
)->compositorclass
, NULL
, comptags
);
562 /* TODO: Check if object was created, how to handle ? */
575 /* FIXME: IMPLEMENT DISPOSE - calling nouveau_close(), freeing cursor bo, gart bo,
576 selectedconnector, gfxdata->compositor, HIDDNouveauAccelFree */
578 /* FIXME: IMPLEMENT DISPOSE BITMAP - REMOVE FROM FB IF MARKED AS SUCH */
580 OOP_Object
* METHOD(Nouveau
, Hidd_Gfx
, CreateObject
)
582 struct HIDDNouveauData
* gfxdata
= OOP_INST_DATA(cl
, o
);
583 OOP_Object
*object
= NULL
;
585 if (msg
->cl
== SD(cl
)->basebm
)
587 struct pHidd_Gfx_CreateObject mymsg
;
589 HIDDT_StdPixFmt stdpf
;
591 struct TagItem mytags
[] =
593 { TAG_IGNORE
, TAG_IGNORE
}, /* Placeholder for aHidd_BitMap_ClassPtr */
594 { TAG_IGNORE
, TAG_IGNORE
}, /* Placeholder for aHidd_BitMap_Align */
595 { aHidd_BitMap_Nouveau_CompositorHidd
, (IPTR
)gfxdata
->compositor
},
596 { TAG_MORE
, (IPTR
)msg
->attrList
}
599 /* Check if user provided valid ModeID */
600 /* Check for framebuffer - not needed as Nouveau is a NoFramebuffer driver */
601 /* Check for displayable - not needed - displayable has ModeID and we don't
602 distinguish between on-screen and off-screen bitmaps */
603 modeid
= (HIDDT_ModeID
)GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
);
604 if (vHidd_ModeID_Invalid
!= modeid
)
606 /* User supplied a valid modeid. We can use our bitmap class */
607 mytags
[0].ti_Tag
= aHidd_BitMap_ClassPtr
;
608 mytags
[0].ti_Data
= (IPTR
)SD(cl
)->bmclass
;
611 /* Check if bitmap is a planar bitmap */
612 stdpf
= (HIDDT_StdPixFmt
)GetTagData(aHidd_BitMap_StdPixFmt
, vHidd_StdPixFmt_Unknown
, msg
->attrList
);
613 if (vHidd_StdPixFmt_Plane
== stdpf
)
615 mytags
[1].ti_Tag
= aHidd_BitMap_Align
;
616 mytags
[1].ti_Data
= 32;
619 /* We init a new message struct */
620 mymsg
.mID
= msg
->mID
;
622 mymsg
.attrList
= mytags
;
624 /* Pass the new message to the superclass */
625 object
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)&mymsg
);
627 else if (SD(cl
)->basegallium
&& (msg
->cl
== SD(cl
)->basegallium
))
629 object
= OOP_NewObject(NULL
, CLID_Hidd_Gallium_Nouveau
, msg
->attrList
);
632 object
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
637 VOID
METHOD(Nouveau
, Hidd_Gfx
, CopyBox
)
639 OOP_Class
* srcclass
= OOP_OCLASS(msg
->src
);
640 OOP_Class
* destclass
= OOP_OCLASS(msg
->dest
);
642 if (IS_NOUVEAU_BM_CLASS(srcclass
) && IS_NOUVEAU_BM_CLASS(destclass
))
644 /* FIXME: add checks for pixel format, etc */
645 struct HIDDNouveauBitMapData
* srcdata
= OOP_INST_DATA(srcclass
, msg
->src
);
646 struct HIDDNouveauBitMapData
* destdata
= OOP_INST_DATA(destclass
, msg
->dest
);
647 struct CardData
* carddata
= &(SD(cl
)->carddata
);
650 D(bug("[Nouveau] CopyBox 0x%x -> 0x%x\n", msg
->src
, msg
->dest
));
655 LOCK_BITMAP_BM(srcdata
)
656 LOCK_BITMAP_BM(destdata
)
658 UNMAP_BUFFER_BM(srcdata
)
659 UNMAP_BUFFER_BM(destdata
)
661 switch(carddata
->architecture
)
669 ret
= HIDDNouveauNV04CopySameFormat(carddata
, srcdata
, destdata
,
670 msg
->srcX
, msg
->srcY
, msg
->destX
, msg
->destY
,
671 msg
->width
, msg
->height
, GC_DRMD(msg
->gc
));
674 ret
= HIDDNouveauNV50CopySameFormat(carddata
, srcdata
, destdata
,
675 msg
->srcX
, msg
->srcY
, msg
->destX
, msg
->destY
,
676 msg
->width
, msg
->height
, GC_DRMD(msg
->gc
));
679 ret
= HIDDNouveauNVC0CopySameFormat(carddata
, srcdata
, destdata
,
680 msg
->srcX
, msg
->srcY
, msg
->destX
, msg
->destY
,
681 msg
->width
, msg
->height
, GC_DRMD(msg
->gc
));
685 UNLOCK_BITMAP_BM(destdata
);
686 UNLOCK_BITMAP_BM(srcdata
);
693 /* If operation failed, fallback to default method */
696 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
700 VOID
METHOD(Nouveau
, Root
, Get
)
704 if (IS_GFX_ATTR(msg
->attrID
, idx
))
708 case aoHidd_Gfx_NoFrameBuffer
:
709 *msg
->storage
= (IPTR
)TRUE
;
711 case aoHidd_Gfx_SupportsHWCursor
:
712 *msg
->storage
= (IPTR
)TRUE
;
714 case aoHidd_Gfx_HWSpriteTypes
:
715 *msg
->storage
= vHidd_SpriteType_DirectColor
;
717 case aoHidd_Gfx_DriverName
:
718 *msg
->storage
= (IPTR
)"Nouveau";
723 if (IS_GFXNOUVEAU_ATTR(msg
->attrID
, idx
))
727 case(aoHidd_Gfx_Nouveau_VRAMSize
):
730 nouveau_device_get_param(SD(cl
)->carddata
.dev
, NOUVEAU_GETPARAM_VRAM_SIZE
, &value
);
731 *msg
->storage
= (IPTR
)value
;
734 case(aoHidd_Gfx_Nouveau_GARTSize
):
737 nouveau_device_get_param(SD(cl
)->carddata
.dev
, NOUVEAU_GETPARAM_GART_SIZE
, &value
);
738 *msg
->storage
= (IPTR
)value
;
741 case(aoHidd_Gfx_Nouveau_VRAMFree
):
744 nouveau_device_get_param(SD(cl
)->carddata
.dev
, NOUVEAU_GETPARAM_VRAM_FREE
, &value
);
745 *msg
->storage
= (IPTR
)value
;
748 case(aoHidd_Gfx_Nouveau_GARTFree
):
751 nouveau_device_get_param(SD(cl
)->carddata
.dev
, NOUVEAU_GETPARAM_GART_FREE
, &value
);
752 *msg
->storage
= (IPTR
)value
;
758 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
761 ULONG
METHOD(Nouveau
, Hidd_Gfx
, ShowViewPorts
)
763 struct HIDDNouveauData
* gfxdata
= OOP_INST_DATA(cl
, o
);
764 struct pHidd_Compositor_BitMapStackChanged bscmsg
=
766 mID
: OOP_GetMethodID(IID_Hidd_Compositor
, moHidd_Compositor_BitMapStackChanged
),
770 D(bug("[Nouveau] ShowViewPorts enter TopLevelBM %x\n", (msg
->Data
? (msg
->Data
->Bitmap
) : NULL
)));
772 OOP_DoMethod(gfxdata
->compositor
, (OOP_Msg
)&bscmsg
);
774 return TRUE
; /* Indicate driver supports this method */
778 #define Machine_ARGB32 vHidd_StdPixFmt_ARGB32
780 #define Machine_ARGB32 vHidd_StdPixFmt_BGRA32
783 BOOL
METHOD(Nouveau
, Hidd_Gfx
, SetCursorShape
)
785 struct HIDDNouveauData
* gfxdata
= OOP_INST_DATA(cl
, o
);
787 if (msg
->shape
== NULL
)
790 HIDDNouveauShowCursor(o
, FALSE
);
797 ULONG curimage
[64 * 64];
798 struct CardData
* carddata
= &(SD(cl
)->carddata
);
800 OOP_GetAttr(msg
->shape
, aHidd_BitMap_Width
, &width
);
801 OOP_GetAttr(msg
->shape
, aHidd_BitMap_Height
, &height
);
804 if (width
> 64) width
= 64;
805 if (height
> 64) height
= 64;
809 /* Map the cursor buffer */
810 nouveau_bo_map(gfxdata
->cursor
, NOUVEAU_BO_WR
);
812 /* Clear the matrix */
813 for (i
= 0; i
< 64 * 64; i
++)
814 ((ULONG
*)gfxdata
->cursor
->map
)[i
] = 0;
816 /* Get data from the bitmap */
817 HIDD_BM_GetImage(msg
->shape
, (UBYTE
*)curimage
, 64 * 4, 0, 0,
818 width
, height
, Machine_ARGB32
);
820 if (carddata
->architecture
< NV_ARCH_50
)
822 ULONG offset
, pixel
, blue
, green
, red
, alpha
;
824 /* The image needs to be premultiplied */
825 for (y
= 0; y
< height
; y
++)
826 for (x
= 0; x
< width
; x
++)
829 pixel
= curimage
[offset
];
830 blue
= (pixel
& 0x000000FF);
831 green
= (pixel
& 0x0000FF00) >> 8;
832 red
= (pixel
& 0x00FF0000) >> 16;
833 alpha
= (pixel
& 0xFF000000) >> 24;
835 blue
= (blue
* alpha
) / 255;
836 green
= (green
* alpha
) / 255;
837 red
= (red
* alpha
) / 255;
839 curimage
[offset
] = (alpha
<< 24) | (red
<< 16) | (green
<< 8) | blue
;
843 for (y
= 0; y
< height
; y
++)
844 for (x
= 0; x
< width
; x
++)
846 ULONG offset
= y
* 64 + x
;
847 writel(curimage
[offset
], ((ULONG
*)gfxdata
->cursor
->map
) + (offset
));
850 nouveau_bo_unmap(gfxdata
->cursor
);
852 /* Show updated cursor */
853 HIDDNouveauShowCursor(o
, TRUE
);
861 BOOL
METHOD(Nouveau
, Hidd_Gfx
, SetCursorPos
)
863 struct HIDDNouveauData
* gfxdata
= OOP_INST_DATA(cl
, o
);
864 struct CardData
* carddata
= &(SD(cl
)->carddata
);
865 struct nouveau_device_priv
* nvdev
= nouveau_device(carddata
->dev
);
868 drmModeMoveCursor(nvdev
->fd
, gfxdata
->selectedcrtcid
, msg
->x
, msg
->y
);
874 VOID
METHOD(Nouveau
, Hidd_Gfx
, SetCursorVisible
)
876 HIDDNouveauShowCursor(o
, msg
->visible
);
879 static struct HIDD_ModeProperties modeprops
=
886 ULONG
METHOD(Nouveau
, Hidd_Gfx
, ModeProperties
)
888 ULONG len
= msg
->propsLen
;
890 if (len
> sizeof(modeprops
))
891 len
= sizeof(modeprops
);
892 CopyMem(&modeprops
, msg
->props
, len
);