Aros/平臺/68k 支援/開發者/HIDD
第一階段:支援具有自定義引導塊的程式,可能使用 trackdisk.device 載入更多軌道,然後其餘部分使用硬體敲擊載入器。
第二階段:支援使用啟動序列引導至 CLI 的程式。
cia.resource(rom/cia)似乎是一種特殊情況(mmakefile.src 中的註釋,它包含 ciaa 和 ciab.resources)。我無法編譯它,甚至不能編譯原始的框架版本。如果我嘗試編譯它,我會收到“<path>/build/bin/amiga-m68k/gen/rom/cia/include/cia_deflibdefs.h: 沒有此檔案或目錄”錯誤,我認為某些東西需要“正常”庫?問題很可能是因為 rom/cia 使用 build_module_simple 將 ciaa/ciab 弄成一個模組。build_archspecific 很可能假設 build_module 用於通用檔案(或者更清楚地說,genmodule 應用程式被使用)。
解決方法是,你需要一個包含 ciaa 和 ciab 的物理模組 cia.resource -> 將 rom/cia 複製到 arch/m68k-amiga/cia,將目標名稱更改為類似 kernel-cia-amiga-m68k 的名稱,只使用它(不要使用 %build_archspecific)。也許只是修復 %build_archspecific?這絕對是一個缺陷。在工作日,我會看看是否有人解決了這個問題。應該不會太難。也許 %build_module_simple 只是缺少使用 %build_archspecific 的能力。我記得我為 %build_prog 修復了這個問題。但是如何將它新增到 kernel-link-amiga-m68k 最終的 rom 映像中?嘗試 make kernel-cia-amiga-m68k-kobj -> 有一個由 %build_module_simple 宏建立的自動化的 something-kobj 目標
順便說一句,addicrvector.c 在成功新增新中斷後缺少 AbleICR(resource, 0x80 | (1 << iCRBit));
現在 cia 資源存在了,我嘗試建立鍵盤 hidd。我拿了 PC 鍵盤 hidd 驅動程式,刪除了所有 PC 特定的程式碼,添加了 Amiga 鍵盤處理(CIA 中斷 + 握手)。在你的 %build_module_simple 呼叫中新增 uselibs="rom"(檢視例如 arch/i386-pc/drivers/keyboard/mmakefile.src)(你可能需要的其他庫是:oop amiga)。再次感謝,“rom”解決了問題。“oop”已經包含了。(我實際上使用了 i386-pc 鍵盤驅動程式作為基礎,它沒有“rom”)。現在它在初始化期間出現在駐留列表中,但 kbd.hidd 似乎沒有初始化。我肯定錯過了一些簡單的東西,再次.. 你的鍵盤 hidd 類需要在模組啟動期間明確地在主鍵盤類中註冊自己(至少在 pc-i386 中是這樣,請參見 i386-pc/drivers/keyboard/startup.c)。但是要做到這一點,主鍵盤類必須已經啟動並執行,從你的日誌來看,你的 kdb.hidd 在 keyboard.hidd 之前初始化。順便說一句,在 pc-i386 中,鍵盤類的優先順序很低(10),因此它即使在 intuition.library 之後也會初始化 - 這意味著你遇到的 input.device 崩潰可能不是由缺少鍵盤類觸發的。正是如此。只需將它的優先順序降低 1/10。鍵盤 hidd 現在載入了(和優先順序太高一樣簡單..)。完全可以不使用 input HIDD 來工作,你只是不會收到事件,僅此而已。EFIKA 就是這樣工作的(它沒有 PS/2 硬體)。我還實現了虛擬的 amigamouse.hidd(目前不做任何事情)。input.device 不再呼叫 alert()。
來自 KickStart 3.0 的“card.resource”想要呼叫 Exec #136(緊隨 TaggedOpenLibrary,#135),但 AROS 沒有實現。或者任何地方有文件提到它。在 3.9 SDK 中,它被列為 'ExecReserved12'。函式的名稱是 ReadGayle()。如果 Gayle 晶片在板上,它將返回 Gayle 晶片的 ID,否則如果不存在此類晶片,則返回零。它首先檢查是否在 DE1000 處也映象了正常的自定義晶片,如果是,則沒有 gayle。然後,它將一個零寫入 gayle ID 暫存器(上面的地址),然後從同一地址執行八次連續讀取。每次讀取的位 7 貢獻一個位到整體 ID。將第一次讀取的位 7 放入位 7,第二次讀取的位 7 放入位 6 等……給出 gayle 晶片的完整 ID。如果結果是 0xff,則此地址沒有晶片,函式返回零。否則,它將返回讀取的資料。顯然,card.resource 需要 gayle ID 來知道 pcmcia 埠的介面是否可用 - 並且這由 gayle 控制。只需建立一個返回 0 的空函式,並在 Amiga 埠中覆蓋它。
滑鼠游標透過驅動程式類的 Get 方法支援硬體游標,你需要返回它(其中一個就足夠了)
case aoHidd_Gfx_SupportsHWCursor:
*msg->storage = (IPTR)TRUE;
return;
case aoHidd_Gfx_HWSpriteTypes:
*msg->storage = vHidd_SpriteType_DirectColor;
你需要實現以下方法
SetCursorShape SetCursorPos SetCursorVisible
如果你需要示例,請檢視 nouveau 驅動程式:AROS/workbench/hidd/hidd.nouveau
你是否檢查了位平面和銅 DMA 是否已啟用,以及銅列表是否看起來正常?(在 UAE 偵錯程式中使用 O 命令)
我現在有一個非常有趣的行為,如果我在 WinUAE(使用最快可能的模式)中正常執行它,軟體會失敗並重置。如果我啟用偵錯程式的“跟蹤”模式(任何斷點都處於活動狀態,並且它開始收集可以使用 H 和 HH 命令檢視的跟蹤資料),它可以正常執行。
最快的可能模式下的偵錯程式可能會將中斷檢測延遲一個 CPU 指令。迴圈精確模式也可以正常工作。你可以在遇到意外異常後停用自動重啟(start.c/Exec_FatalException)?它使除錯變得令人討厭(我用無限迴圈替換它)
gallium 的維護者檢視過這個嗎?我不知道我們是否可以在 gallium 中安全地使用 Disable()/Enable()。這很可能會殺死或嚴重影響效能。我假設 gallium 給 m68k 帶來問題。你可以做兩件事
a) 停用為 m68k 架構構建 libgalliumauxiliary、gallium.library、mesa.library、gallium.hidd 和 softpipe.hidd(例如,使用你自己的 workbench-libs 和 workbench-hidds 目標)
b) ifdef 你的補丁,使其僅在 m68k 架構上應用(因此它將是 PIPE_ATOMIC_OS_AROS_M68K),而其他架構繼續使用預設方法(GCC 指令)
你也可以嘗試在真實自動配置快速 RAM 中獲得 exec(在 ConfigChain() 呼叫之後),如果你還有太多空閒時間:) 你是在說移動“引導任務”堆疊,還是將所有 Exec 從 ROM 移動到 RAM?
如果是前者,它應該在第一個 CLI 程式的 CreateProcess() 期間自動發生。我只需要修復記憶體分配指標,這樣 'old' Boot Task 堆疊就可以在 RemTask(NULL) 上被正確地釋放
如何為模式標籤列表設定正確的本機模式 ID?(hires、lace、pal、ntsc 等)。請參見 AddDisplayDriverA() 的 DDRV_MonitorID 標籤。然後你可能需要對 graphics.hidd 的 ModeID 處理進行子類化,因為你會得到另一個 ModeID 結構。我建議你每個顯示器模式都同步一次(我的意思是 PAL 是一個同步,NTSC 是另一個同步,多掃描是第三個同步,等等)。只會有一個畫素格式,ModeID 中的其他位將是同步修飾符。
zzzz xx yy
zzzz 實際上是驅動程式編號。它們按順序分配,從 0x0010 開始。這樣,最多 0x000F 的數字將被保留。我專門為 Amiga 驅動程式這樣做。
xx 和 yy 是同步編號和畫素格式編號。我現在不記得哪個是哪個,但實際上並不重要。
因此 zzzz 由 graphics.library 處理,而 xx yy 由 graphics.hidd 處理。
Amiga 晶片組驅動程式需要佔用保留區域(如果我記得正確的話,是 0x0000 - 0x000A)。可以使用 DDRV_MonitorID 標籤顯式請求驅動程式編號。現在你需要將 zzzz 轉換為 zzzW,其中 W 也是特定於模式的東西。如果你檢視 AddDisplayDriverA(),你會看到 AROS_MONITOR_ID_MASK 硬編碼值。其中一個變體是實現 DDRV_IDMask 標籤,它將允許覆蓋掩碼值。
好的,這已經完成了。現在讓我們處理 xx 和 yy。
你可能需要在你的驅動程式中覆蓋 ModeID 例程。說實話,我完全沒有檢視過這部分,所以我無法告訴你將此功能合併到使用附加屬性的基本類中是否有效。
現在關於另一種可能的方法…
如果你檢查 graphics.library 程式碼,你會看到一個記憶體驅動程式例項。目前它是“hidd.graphics.graphics”的例項,它表示儲存在 RAM 中的不可顯示點陣圖。所有臨時平面點陣圖物件都由這個驅動程式擁有。
也許在這裡例項化晶片組驅動程式會非常有效。由於晶片組驅動程式仍然是 graphics.hidd 的子類,它仍然支援 RAM 中的塊狀點陣圖。但它將為平面點陣圖新增缺少的功能。
這種變體的第二個要點:由於 graphics.library 知道這個特定的驅動程式,它可以以特定的方式新增它的模式,你不需要為 AddDisplayDriverA() 引入新的標籤。事實上,我還沒有實現這個標籤,因為它很容易透過不正確使用它來破壞整個 GFX 系統,並且除了晶片組驅動程式之外,任何人都不需要它。
我相信它們各有優缺點。由你決定如何實際處理它。也許你會發明你自己的方法。無論如何,我相信你需要以某種方式擴充套件 GFX 子系統。我注意到 graphics 在這裡和那裡內部檢查 aros modeid 部分是否有效(xx 和 yy 部分必須小於總同步和畫素格式)這會變得很混亂…
{ aHidd_PixFmt_ColorModel , vHidd_ColorModel_Palette },
// is following maximum or do I need to have multiple pixformat/depth pairs?
{ aHidd_PixFmt_Depth , 4 },
What does following tags mean in planar mode? (they need to be included or
pixformat gets rejected)
They don't make much sense if bitmap is planar.
{ aHidd_PixFmt_BytesPerPixel, 1 },
{ aHidd_PixFmt_BitsPerPixel , 1 },
{ aHidd_PixFmt_StdPixFmt, vHidd_StdPixFmt_Native },
{ aHidd_PixFmt_BitMapType, vHidd_BitMapType_Planar },
它們的意思就是它們的意思。當然,BytesPerPixel 攜帶的是虛擬值。實際上,StdPixFmt 將始終為 vHidd_StdPixFmt_Plane。
由於某種原因,引導選單在 intuition.library OpenScreen() 內部的某個地方崩潰了。似乎發生在 intuition_mis.c 中的深處,DoMethodA() 呼叫..(jsr 到不存在的地址)
D(bug("[intuition] RenderScreenBar: ScrDecorObj @ %p, DecorUserBuffer @
%p\n", ((struct IntScreen *)(scr))->ScrDecorObj, ((struct IntScreen
*)(scr))->DecorUserBuffer));
DoMethodA(((struct IntScreen *)(scr))->ScrDecorObj, (Msg)&msg); }
D(bug("[intuition] RenderScreenBar: Update gadgets .. \n"));
gfx hidd 更新已提交,現在看起來好多了。
- 支援 24 位 AGA 顏色(如果檢測到 AGA)
- 顯示大小的硬體值不再硬編碼。
- 使用隔行掃描模式(預設螢幕尺寸為 640x480+,更準確的縱橫比)。
但是
- 沒有 shres/hires/lores 和 lace/non-lace 的自動選擇。
- 僅使用軟體blitting(= 緩慢)。
基於塊的驅動程式(記憶體中的塊陰影點陣圖,使用 chunkytoplanar 轉換為 CHIPRAM 中的真實點陣圖)會更快,除了在最慢的真實 Amiga(如 A500)上。晶片 RAM 很慢。blitting 很慢。
據我所知,一些遊戲在 040 或更高版本上的 c2p 例程可以以複製速度(晶片 RAM 寫入頻寬)進行轉換。
由於 AROS 或 graphics.library 中沒有任何內容依賴於直接點陣圖訪問,因此你甚至可以擁有一個真彩色模式(驅動程式使用真正的 ARGB32 或類似的塊緩衝區作為陰影點陣圖),該模式在進行 c2p 的同時即時抖動到 256 或 16(或任何)種顏色。對於驅動程式之外的所有內容,它都是一個真正的真彩色模式。不過,使用平面定製晶片組圖形作為虛擬塊 C2P 幀緩衝區對我來說不夠 Amiga 風格,而且在任何真實的 Amiga 上都太慢了)。
如何安裝這個監視器?monitorclass.c 說你不應該碰它。我在現有的 PC hidd 中也沒有找到任何有趣的東西。沒有奇怪的地方。基本上 monitorclass 允許處理多顯示器輸入。此外,它還處理滑鼠精靈,因為 graphics.library 函式並不非常適合多監視器環境。其他東西只是 MorphOS API 的重新實現(為了與某些東西相容)。所以,如果沒有 monitorclass 物件,Intuition 就不知道你的監視器(而 graphics 仍然知道),並且無法在其上處理輸入。平面數增加到 5(如果為 AGA),因為如果顯示器平面數少於此,則預設精靈顏色(17-19)不會更新。如何正確處理?(游標點陣圖是否有調色盤?) OpenScreen() 應該處理這個問題。沒有人用 Amiga 硬體測試過它,所以檢查一下。據我所知,我對滑鼠精靈部分進行了很好的註釋。
一些私有依賴項已被刪除,並且在 intuition 中更改了 monitorclass 物件查詢。由於它們知道監視器 ID 和掩碼,因此可以透過 ModeID 找到描述符。
- 第一個問題:為什麼它們的掩碼範圍如此廣 (0xF00000000)?我假設晶片組驅動程式的掩碼為 0xFFF00000。
- 為什麼你為 UAE 驅動程式使用自定義 ID?實際上,我認為這就是原因。也許兩個驅動程式碰巧具有相同的監視器 ID(ModeID 部分,掩碼中有 1)。因此,Intuition 中的 FindMonitor() 函式找到了錯誤的監視器物件,並且 Intuition 的輸入處理程式無法查詢正確的螢幕。
在設計 ID 分配方案時,不同的驅動程式獲得不同的 ID。自動分配測試得很好,但從未打算擁有如此廣泛的掩碼。這就是 RTG ID 以 0x00100000 開頭的理由。在晶片組模式下,最右邊的五個數字會變化,第六到第八個數字始終為 0,這就是保留基於此的原因。它從未打算擁有 0xF0000000 掩碼。
我在 openscreen.c 中添加了這一點,現在 Intuition 分配了顏色 17 到 19,但 SetColors 點陣圖方法沒有獲得任何 >15 的調色盤條目。
#if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
spritebase = 16;
#else
spritebase = (ns.Depth < 5) ? (1 << ns.Depth) - 8 : 16;
#endif
你說的所有事情都完成了。那是簡單的一部分。(它有很好的文件記錄,例如 vesa.hidd 做了與預期相同的操作) 問題是 graphics 或 intuition 內部的東西。
intuition/misc.c: this calls HIDD SetCursorPos() normally.
static void SetPointerPos(struct MonitorData *data, struct IntuitionBase
*IntuitionBase)
{
ULONG x = data->mouseX;
ULONG y = data->mouseY;
DB2(bug("[monitorclass] SetPointerPos(%d, %d), pointer 0x%p\n", x, y,
data->pointer));
if (data->pointer)
{
/* Take HotSpot into account */
x += data->pointer->xoffset;
y += data->pointer->yoffset;
/* Update sprite position, just for backwards compatibility */
data->pointer->sprite->es_SimpleSprite.x = x;
data->pointer->sprite->es_SimpleSprite.y = y;
}
DB2(bug("[monitorclass] Physical coordinates: (%d, %d)\n", x, y));
HIDD_Gfx_SetCursorPos(data->handle->gfxhidd, x, y);
}
void MonitorClass__MM_SetPointerPos(Class *cl, Object *obj, struct
msSetPointerPos *msg)
{
struct MonitorData *data = INST_DATA(cl, obj);
data->mouseX = msg->x;
data->mouseY = msg->y;
SetPointerPos(data, IntuitionBase);
}
Above is called from intuition/misc.c:
void MySetPointerPos(struct IntuitionBase *IntuitionBase)
{
Object *mon = GetPrivIBase(IntuitionBase)->ActiveMonitor;
if (mon)
DoMethod(mon, MM_SetPointerPos, IntuitionBase->MouseX,
IntuitionBase->MouseY);
}
IntuitionBase->ActiveMonitor 始終為 NULL。所有 SetCursorXXX() 函式也存在相同的問題,NULL ActiveMonitor -> 不呼叫任何滑鼠例程。
如果我在此函式中新增 "bug("x=%d y=%d);"(在 if (mon) 之外),當我移動滑鼠時,我將按預期獲得除錯訊息。
好的,也許這對你有所幫助:當驅動程式呼叫 AddDisplayDriver 時,graphics.library 註冊一個新的驅動程式,並通知 intuition.library 新驅動程式已註冊。這樣,intuition.library 就可以建立一個新的監視器物件。但是,為了獲得此通知,intuition.library 必須首先向 graphics.library 註冊。
也許你的初始化順序如下
graphics.library amiga.hidd intuition.library
我認為在這種情況下,Intuition 可能不會收到通知,並且可能不知道已載入了驅動程式。
每個 graphics hidd 函式都在超類中以 "通用" 方式實現,使用來自具體實現的 PutPixel/GetPixel,你需要在 hidd 中實現所有繪圖函式以擺脫使用 PutPixel 的 "超類"。(我建議從 "改進" CopyBox 開始,然後繼續使用 PutImage 和 PutImageAlpha)。CopyBox 不在點陣圖類中。
游標有兩種工作方式
- 在 fakehidd 上進行模擬
- 原生模式
據我所知,為了使模擬正常工作,你的驅動程式需要是幀緩衝區驅動程式(aHidd_Gfx_NoFrameBuffer = FALSE),並且你需要實現 Show 方法來呼叫超級方法。這種模擬只是在你螢幕上為你繪製游標(恢復舊的備份的 64x64 圖塊,備份新的 64x64 圖塊,繪製游標)。
對於原生模式,你需要實現 SetCursorVisible、SetCursorPos 和 SetCursorShape,並在 SetCursorPos 中自己進行 "繪製"。你需要將你的驅動程式標記為 NoFrameBuffer = TRUE,並告訴系統你支援硬體游標 aHidd_Gfx_SupportsHWCursor = TRUE。此外,在 show 方法中,你必須返回接收到的點陣圖,並且不要呼叫超級方法。永遠不要觸碰 gfx 驅動程式(hidd 類)以上的任何內容,以使游標正常工作。
Picasso96 支援以下高色模式
RGBFB_R5G6B5PC, /* HiColor16 (5 bit R, 6 bit G, 5 bit B), format: gggbbbbbrrrrrggg */ RGBFB_R5G5B5PC, /* HiColor15 (5 bit each), format: gggbbbbb0rrrrrgg */ RGBFB_R5G6B5, /* HiColor16 (5 bit R, 6 bit G, 5 bit B), format: rrrrrggggggbbbbb */ RGBFB_R5G5B5, /* HiColor15 (5 bit each), format: 0rrrrrgggggbbbbb */ RGBFB_B5G6R5PC, /* HiColor16 (5 bit R, 6 bit G, 5 bit B), format: gggrrrrrbbbbbggg */ RGBFB_B5G5R5PC, /* HiColor15 (5 bit each), format: gggrrrrr0bbbbbbgg */
UAE 預設值為 RGBFB_R5G6B5PC(無需轉換,與正常的低端 16 位模式匹配),我認為大多數 UAE 埠甚至不支援其他高色模式。
是否可以在大端 CPU(如 68k)上定義此模式?(我不知道單個顏色分量移位和掩碼如何工作。我知道這不是必需的,8 位和 32 位已經足夠了,但我希望擁有完整的實現:)。
我還有另一個問題:BitMap_GetImage 和 PutImage(+LUT 變體),"pixels" 陣列的格式是什麼?始終與點陣圖相同,還是始終為 32 位或 8 位?我沒有找到足夠好的示例或文件。這些是最後剩下的未實現的方法。傳入/請求的畫素緩衝區的格式在訊息中可用:msg->pixFmt。
你可以獲得兩種偽格式:Native 和 Native32。據我瞭解,gfx 系統 Native 意味著 "與呼叫該方法的點陣圖物件相同",而 Native32 意味著 "與呼叫該方法的點陣圖物件相同,但打包在 4 位元組的 "畫素" 中"。
如果我們有 8 位(256 色)點陣圖,並且請求了 Native32,如何填充畫素陣列?(1 位元組資料 + 3 個零?3 個零 + 1 個位元組?某些顏色轉換?) 基類中已經存在你可以使用的方法
GetMem32Image8 ConvertPixels PutMem32Image8
檢查 /workbench/hidds/hidd.nouveau/nouveau_accel.c
HiddNouveauWriteFromRAM HiddNouveauReadIntoRAM
我認為你在這些函式中看到的 switch/case 級聯對於每個驅動程式的 GetImage/PutImage 都是通用的。例如,讓我們以 GetImage 方法為例。它在點陣圖物件上呼叫,請求將此點陣圖物件的指定框 (msg->x, msg->y, msg->width, msg->height) 傳輸到記憶體緩衝區 (msg->pixels),該緩衝區具有給定的步長 (msg->modulo) 和給定的畫素格式 (msg->pixFmt)。為此,你首先檢查給定的(請求的)畫素格式,看它是否是 Native、Native32 還是其他。在前兩種情況下,你隨後檢查輸入 bytesperpixel 值,並根據此值決定使用哪個現有的 CopyMemBoxXXX 或 GetMemXXXImageYYY 方法。如果請求的格式不同於 Native 或 Native32,你需要使用 ConvertPixels 方法,該方法將為你進行轉換。實現你的驅動程式時,你不必擔心格式在轉換期間的記憶體組織方式,因為這已經在 CopyMemBox/GetMemImage/ConvertPixels 方法中實現了。
請注意,ConvertPixels 中使用的通用轉換方法有點慢。還有更具體的、更快的 method。你可以透過執行 tests/patchrgbconv 來切換到這些 method。你也可以像我在 nouveau 中做的那樣,在驅動程式本身中修補這些方法,這樣使用者就不必擔心這個問題。
既然我們正在談論補丁,我知道你不想為第三方 Amiga 硬體編寫驅動程式,但你是否認為在 AROS m68k 上使用 Picasso96 驅動程式有解決方案?我不是要你做,只是想知道是否可以在上面安裝 Picasso96,或者你編寫的程式碼是否允許使用 .chip/.card 檔案,以便 RTG 可以用在真實的 Amiga 上。我知道 Deneb、scsi 等的原始驅動程式應該在 AROS m68k 中開箱即用。Uaegfx hidd 在內部使用 .card API 與 UAE 端通訊。修改它以使用 "真實的" Picasso96 驅動程式和卡應該相當容易。(我可以做到這一點,我有一臺 A3000,但沒有擴充套件卡。從未真正關心顯示卡..) 大多數驅動程式應該可以正常工作。
螢幕點陣圖在可見時被鎖定 (bm->locked 變數)(以防止它們被交換),但後來即使某些其他螢幕點陣圖已變為可見點陣圖,也從未被解鎖。因此,所有螢幕點陣圖永遠保留在 VRAM 中。據我所知。
速度
如果有一些 gfx 函式,驅動程式本身沒有處理,那麼回退函式通常會很慢或非常慢。對於 RAM/VRAM 可交換點陣圖來說更是如此,因為需要點陣圖鎖定。回退沒有最佳化,而且它們永遠不可能超級快,因為 AROS gfx 系統的設計方式是不依賴於直接訪問 gfx 驅動程式點陣圖(或其他點陣圖)的畫素資料。它可以嘗試在回退函式中獲取直接訪問許可權,但目前它主要不這樣做,因此僅使用間接訪問畫素資料,例如透過 putpixel/getpixel 或 putimage/getimage。
目前 uaegfx 驅動程式本身沒有處理的一件事是,源點陣圖 pixfmt 與目標 pixfmt 不同,並且至少一個位圖位於 RAM 而不是 VRAM 中的 blit。對於 COPY drawmode/minterm,至少應該可以使用 HIDD_BM_ConvertPixels(如果兩個點陣圖都是 uaegfx 點陣圖)或 HIDD_BM_PutImage/GetImage(如果其中一個位圖是外部點陣圖)來處理/實現它。說到 drawmode,至少應該處理 INVERT 和 CLEAR(使用 BMF_CLEAR 分配的點陣圖可能會觸發此操作)。
畫素 fmt 轉換例程:據我所知,AROS 68k 只內建了一些改進的例程(以前在 SYS:tests/patchrgbconv 中的內容)(ROM 中的空間限制)。
graphics.library/Text(): 將單個字型字元放入臨時位平面中的程式碼非常沒有最佳化。這個模板位平面然後使用 BltTemplate() 渲染到螢幕上。如果有人想改進這個,他可以嘗試在 AmigaOS(也許甚至 AOS4 或 MorphOS)上使用一個小程式編譯/最佳化這個(rom/graphics/text.c),該程式使用 SetFunction() 將它修補到系統中。不依賴於 AROS 內部,所以沒有問題(在 AOS3 上停用抗鋸齒相關的功能)。然後比較這比原始 AOS 函式慢多少。然後最佳化,直到它不再糟糕... 然後貢獻回 AROS。
平面點陣圖:在內部,大多數 AROS 點陣圖是點陣圖物件(像 boopsi 一樣),但並非所有都是。手工製作的(比如使用 InitBitMap() 的)不是,據我所知,即使使用 AllocBitMap() 分配的平面點陣圖也不是點陣圖物件。因此,在圖形函式期間,這些會在執行時被包裝成點陣圖物件,因為圖形系統只使用這些點陣圖物件,而不是使用 graphics.library 中已知的“struct BitMap *”。我注意到的一件在包裝中很愚蠢/很慢的事情是,planarbm 類在 SetbitMap() 方法中總是呼叫 RegisterPixFmt 來註冊包裝的平面點陣圖的 pixfmt。因此,在每個涉及平面點陣圖的圖形函式中,都會重新註冊一個 pixfmt。應該更改為僅在先前尚未註冊匹配的 pixfmt 時才這樣做。
圖示:在 AROS 中,載入像這樣的東西(以及字型)很慢,因為 AROS 可以是 32 位、64 位、大端序、小端序,並且所有可能的變體都使用相同的程式碼。在 AOS(或 AOS4 或 MOS)中,他們的位元組序固定為“大端序”,系統固定為 32 位。因此,他們基本上可以像記憶體中一個結構一樣,以一個塊的形式讀取這些內容。AROS m68k-amiga 也可能已經優化了載入(#if AROS_BIG_ENDIAN 等像他們在 AOS68k 環境中那樣做),但目前沒有。
也許我錯過了一些重要的東西,但似乎 gfx hidds 需要指定每個支援的深度值。例如,如果你想完全支援 AGA,hidd 應該有 8 種不同的畫素格式(而 OCS/ECS 則有 4 或 5 種,具體取決於水平解析度)。它不應該自動生成所有較低深度的畫素格式嗎?
這真的會減慢真實 Amiga 上的圖形速度,特別是在非 AGA 機器上,因為它現在總是強制使用 4 平面高解析度,這會消耗所有晶片 RAM 頻寬並佔用太多記憶體。
另一個很大的相容性問題是錯誤的模式 ID。這需要一個有效的解決方案。我也希望有一個針對模式 ID 問題的解決方案,我真的不明白由某個外部實體動態生成模式 ID 的意義。關鍵在於:同一個驅動程式可以被例項化多次。例如,你可以有兩張類似的顯示卡,每張顯示卡都可以有多個輸出。這樣,對於兩張 Radeon 顯示卡,你將有四個相同驅動程式的例項。你會分配什麼模式 ID?以及如何分配?在 CyberGraphX 中,你使用首選項程式手動建立模式 ID。我決定這不是很方便,並實現了對監視器 ID(模式 ID 的最高位字)的動態生成。其餘的(畫素格式和同步數字)實際上來自舊實現。我在這裡沒有發明任何新東西。也許它仍然有一些缺點,但我認為它是可以接受的。無論如何,程式設計師不必手動分配 ID。
在 RTG 驅動程式中添加了更多模式,突然所有其他模式都獲得了新的 ID... 顯然,至少一些 m68k RTG 程式認為“太小”的模式 ID 數字 = 本地平面模式。什麼是“太小”?
現在關於你想要知道的事情... 當我實現新的 ID 方案時,我實際上留出了空間用於 Amiga ID(即,用於你)。為了說明:顯示模式 ID 分為兩半:最高位一半是“監視器 ID”,最低位一半是原始模式 ID 本身(同步 + 畫素格式)。HIDD 只知道後一半,監視器 ID 由 graphics.library 維持。
如果你仔細檢視程式碼,你會發現 ID 編號從 0x0010 開始。沒有 RTG 驅動程式以小於此 ID 的 ID 新增。你的驅動程式需要佔用這個保留的空間。此外,它需要為其模式指定 0xFFF00000 掩碼,因為 Amiga 模式 ID 可以表示為 0x000X XXXX。
目前 AddDisplayDriverA() 缺少指定掩碼的可能性。但是,你可以指定起始 ID(使用 DDRV_MonitorID 標籤)。有以下可能的解決方案
- a 實現 DDRV_IDMask 標籤。
- b 實現一個類似 DDRV_AmigaModes 的單個布林標籤,它會自動將 Amiga 模式分配給驅動程式。
- c 使 m68k 上的 graphics.library 明確例項化晶片組驅動程式,而不是像其預設驅動程式一樣使用虛擬記憶體驅動程式。
我不喜歡 (a),因為不恰當地使用這個標籤很容易破壞 graphics.library。我只會考慮 (b) 或 (c) 選項。也許 (c) 甚至更好,因為它會自動使所有屬於晶片組驅動程式的平面點陣圖成為平面點陣圖。實際上,由你決定該怎麼做以及如何實現它。但請不要破壞整個 ID 方案。我對此思考了很多。我在實現它之前詢問了其他人,但沒有人提出任何替代方案。
模式 ID 由“其他人”生成,對支援模式的任何修改都會重新編號模式 ID。(這在模擬中尤其是一個問題,因為使用者可以選擇啟用哪些位深度,或者是否想要 BGR 或 RGB 等。)
關於 rtg 和非 rtg 模式(我認為他指的是模式 ID)
everything below monitor-id $00100000 is an amigamode all other ids are standing for rtg if you found anything over $00100000 use the cgfx-functions to identify the gfxcard p96 supports the functions of cgfx
我自己,我以為 cgx 提供靜態模式 ID,但在 p96 上定義解析度的前四位數字取決於模式宣告的順序,因此它們是半隨機的,最後描述深度/位順序的四位數字是硬編碼到它們代表的模式的。以下是我在我 voodoo3 系統上找到的代表特定位順序的 p96 模式 ID 最後四位數字的值。
xxxx1000 = 8bit xxxx1100 = 16bit pc xxxx1102 = 16 bit xxxx1201 = 24bit xxxx1300 = 32bit argb xxxx1303 = 32bit bgra
0x8000100e,即 DIPF_IS_HAM | DIPF_IS_PF2PRI | DIPF_IS_DUALPF | DIPF_IS_EXTRAHALFBRITE(+ 位 31 設定,這顯然是一個遊戲錯誤。)
不幸的是,這意味著即使使用 RTG 顯示,也需要以某種方式模擬 AOS 原始模式 ID(在這種情況下,所有本機晶片組特殊位都需要歸零)。
如何新增 AROS 圖形系統可以提升為標準 hidd 模式的“標準”監視器模式 ID?(就像真實 m68k-amiga RTG 硬體在啟用模式提升時所做的那樣)。請參閱更新後的 AddDisplayDriverA() 文件。我為此添加了 DDRV_ID_Mask 標籤。“請注意,要使此功能正常工作,你還需要覆蓋驅動程式類中的模式 ID 處理。hidd.graphics.graphics 基本類提供的預設方法假定模式 ID 的整個低位字指定了顯示模式。”
覆蓋模式 ID 處理究竟意味著什麼?過載 GetMode、GetSync、NextMode 等方法。
例如,PowerPacker 這樣做
- 呼叫 QueryOverscan(0x29000, &rect, OSCAN_TEXT);,這會導致失敗。
- PP 忽略返回值,rect 包含隨機記憶體內容。
- 將垃圾 rect 內容複製到 NewScreen 結構的螢幕位置和大小。
- 新增一些 OpenScreenTags() 標籤,包括模式 ID 標籤 = 0x29000
- 當然,螢幕無法開啟(不存在的模式 ID,完全錯誤的螢幕寬度和高度)。
0x29000 = PAL_MONITOR_ID | HIRES_KEY.
至少 PAL_MONITOR_ID、NTSC_MONITOR_ID、HIRES_KEY 和 LORES_KEY 組合應始終受支援並返回匹配的解析度。OpenScreen() 中有一些提升程式碼(從 MorphOS 遺留下來的),檢查它並在需要時修復(參見 openscreen.c,第 597 行)。我猜這很容易,將一個驅動程式標記為“首選”(驅動程式可以有優先順序嗎?)。它們可以。但是,目前它們沒有。
如果詢問“其他”驅動程式的模式 ID,只需從首選驅動程式模式列表中找到足夠相似的模式?目前,BestModeIDA() 會遍歷所有驅動程式,也許我們應該真的擁有一個“預設”驅動程式,由使用者指定。然後,我們應該為使用者關於監視器的首選項開發一些概念。這可以包括指定首選監視器、高階模式提升、描述監視器放置等。
顯然,你需要為所有平面數量定義畫素格式,而不僅僅是描述最大支援平面數量的畫素格式。這意味著例如,需要為單個 AGA 解析度提供 8 個不同的模式 ID。(320x256x1、320x256x2... 320x256x8 以及所有其他解析度的相同模式 ID)
將 8 個模式 ID(或 OCS/ECS 上的 4/5 個模式 ID)放入單個官方文件模式 ID 位中是相當困難的。也許可以新增到 AROS 程式碼中,使自動 ID 生成僅建立高於 0x10000000 的 ID?所有低於此 ID 的 ID 可以透過手動 ID 建立。如果僅定義了 320x256x8,則所有較低平面模式請求始終“提升”為 8 平面。
另一個需要在本地模式能夠工作之前修復的問題。需要 aoHidd_BitMap_Depth(出於某種原因,它被註釋掉了,並且沒有在所有地方處理,比如在 AllocBitmap() 中)。AllocBitMap() 將寬度、高度、畫素格式傳送到 HIDD,但沒有傳送深度。這對支援 m68k-amiga 晶片組模式來說非常必要。它需要每個解析度一個畫素格式/模式 ID,而不是每個(解析度 * 可用深度)一個畫素格式。如果你檢視 allocbitmap.c 中的第 392 行,你會看到深度實際上是從畫素格式(* 或從點陣圖物件 - 我不理解這一部分)複製的。根據我的理解,驅動程式的作用是正確地處理這種情況。
AllocBitmap(depth=1 bit, friend bitmap depth=2)
它應該分配一個深度為 2 的點陣圖,完全忽略傳遞的深度。這段程式碼位於根 GraphicsClass(第 1177 行)。我將其放在 allocbitmap 中,因為模式 ID 也從那裡(而不是在驅動程式中)的 friend 點陣圖複製,因為從技術上講,塊狀模式 ID 也包含深度。我還比較了你和 nouveau 的 bitmap New 方法,我注意到你使用了
OOP_GetAttr(o, aHidd_BitMap_Depth, &depth);
而我使用了
OOP_GetAttr(o, aHidd_BitMap_PixFmt, (APTR)&pf); OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
這意味著你正在使用傳遞的深度(參見根 BitMap 類 New 方法),而我正在使用從 friend 點陣圖的畫素格式中獲取的深度。這是因為處理平面模式和塊狀模式的方式不同嗎?是的。平面模式的深度與畫素格式(模式 ID)分開。平面模式的 pixfmt_depth = 畫素格式的最大支援深度(在 OCS/ECS 和 AGA 上有所不同)。
任何假定 pixfmt_depth = 點陣圖的當前深度的非驅動程式程式碼都不能與平面模式一起正常工作。我在這個 ML 中多次抱怨過這個與 AOS 不相容的設計問題,直到我重新添加了註釋掉的 aHidd_BitMap_Depth 等等,你錯過了嗎?:)
我做錯什麼了嗎,還是這個 gfx hidd 功能缺失?順便說一句,據我所知,至少 rastport 中的位平面掩碼欄位應該被傳遞給 hidd rectfill() 及其朋友,如果我們要處理所有低位平面技巧,在最壞的情況下,需要最小項陣列(它將在複雜情況下取代 drawmode 和 mask),如果 dpaint 螢幕模式請求器要正常工作。
HIDD_BM_ConvertPixels() - 它似乎沒有完全從塊狀轉換為平面。即 vHidd_StdPixFmt_ARGB32 -> vHidd_StdPixFmt_Plane 執行 LUT 變換,但沒有將畫素重新打包到平面模式中。這是 HIDD_BM_ConvertPixels() 的工作嗎?如果是,在 AROS 中是否有任何我可以重複使用的“眾所周知的”塊狀 -> 平面例程?
aHidd_PixFmt_BitsPerPixel:顯然應該為每個畫素的位數,但似乎只被設定,從未使用。aHidd_PixFmt_BytesPerPixel:對於平面格式,應該將其設定為多少?1?0?(- 深度)?aHidd_PixFmt_Depth:這應該是平面的平面數。對於塊狀模式,這應該為 0 嗎?
事實上,這可能是一個不完整的實現。歷史上,vHidd_StdPixFmt_Plane 僅指單平面單色點陣圖,它用於渲染字型。後來它被擴充套件,大約一年前,我刪除了原始的字型繪製例程。
建議...
塊狀格式
aHidd_PixFmt_Depth == 1 aHidd_PixFmt_BytesPerPixel == Number of bytes to store a pixel, if
畫素是位元組對齊的。0 表示“打包畫素”(即非平面的 2 色點陣圖)。
aHidd_PixFmt_BitsPerPixel == Number of valid bits per pixel chunk.
如果 BytesPerPixel == 0,則表示打包畫素的打包。
示例
- Hercules 單色:Depth = 1, BytesPerPixel = 0, BitsPerPixel = 1
- CGA 4 色模式:深度 = 1,每畫素位元組數 = 0,每畫素位數 = 2
- VGA 256 色模式:深度 = 1,每畫素位元組數 = 1,每畫素位數 = 8
- RGB 15 位模式:深度 = 1,每畫素位元組數 = 2,每畫素位數 = 15
平面格式遵循相同的規則,但請注意,每個平面每個畫素可能有多個位。
aHidd_PixFmt_Depth = 1..8 (Number of planes) aHidd_PixFmt_BytesPerPixel == Number of bytes to store a pixel, if
畫素按位元組對齊,0 表示“打包畫素”(例如 2 色點陣圖非平面)
aHidd_PixFmt_BitsPerPixel == Number of valid bits per pixel chunk.
如果 BytesPerPixel == 0,則表示打包畫素的打包。
示例
- Amiga 4 色模式:深度 = 4,每畫素位元組數 = 1,每畫素位數 = 1
- Amiga 256 色模式:深度 = 8,每畫素位元組數 = 1,每畫素位數 = 1
- 有些人將 24+8 位 RGBA 組成,每個平面有 8 位單色或 alpha:深度 = 4,每畫素位元組數 = 1,每畫素位數 = 8
ConvertPixels 用於平面格式,我對某些欄位的含義有點困惑。也許列表不完整,但是有沒有像“每行位元組數”或“包含填充的寬度”這樣的東西?有可獲取的 aHidd_BitMap_BytesPerRow。但是,不支援填充。我以前在平面點陣圖中需要這個,我引入了 aHidd_BitMap_Align。對齊不影響 BytesPerRow 值,該值始終返回為 Width * BytesPerPixel(取自點陣圖的(pixelformat))。這可能是錯誤的,應該考慮對齊。此外,BytesPerRow 將為平面點陣圖計算錯誤,該屬性需要在 planarbm 類中過載。我看來,ConvertPixels 從來不適合平面到塊狀的轉換。但只適用於 LUT 到 LUT。或者 LUT 到 TRUECOLOR。或者 TRUECOLOR 到 TRUECOLOR。其中 LUT 基本上意味著塊狀畫素佈局。ConvertPixels 存在是為了支援像 WritePixelArray()、WriteLUTPixelArray()、ReadPixelArray()、WriteChunkyPixels() 這樣的函式。
所以,如果我理解正確,GetImage/PutImage 用於平面應該處理塊狀/平面轉換,並將當前 ConvertPixels 作為助手,而不是呼叫根類的 GetImage/PutImage 及其對 ConvertPixels 的使用。目前,PlanarBM 正在為 PutImage 上的非本機 PixFmt 型別呼叫根類。你暗示 PlanarBM 應該自己處理所有傳入型別的轉換,對嗎?
所有程式碼都可以保持原樣,內部點陣圖的外觀不應該有任何影響(或者有什麼不起作用?),因為圖形庫和 hidd 東西不依賴於它的外觀。當代碼需要檢視點陣圖畫素時,所有操作都使用畫素緩衝區 == 畫素陣列 == 塊狀陣列以及像 PutImage/GetImage 這樣的函式,即使對於平面點陣圖和 pixfmt == Native 或 Native32 也會寫入/讀取塊狀畫素陣列/緩衝區。(參見 rom/hidds/graphics/planarbm.c)
所以,如果有人使用平面點陣圖類編寫圖形驅動程式,那麼 PutImage/GetImage 和 pixfmt==Native|Native32 不應該使用/返回平面資料,而是塊狀資料。
理論上也不存在單一的平面格式。例如交錯與否。MSBFirst/LSBFirst(參見 X11)。類似 Atari 的平面格式。隱式對齊是一種選擇,但如果 API 是無遺留的,確實更方便將 BytesPerRow 和 Pad 分開。從點陣圖複製到點陣圖時,填充通常只是浪費的空間。此外,單獨宣告它可以避免計算錯誤。
這也有助於區分平面與塊狀/真彩色格式。aHidd_PixFmt_BitsPerPixel:應該是每個畫素的位數,顯然,但似乎只設置,從未使用。真的嗎?它至少可以在註冊新的畫素格式時用於比較。除非你確信自己研究了所有程式碼,否則不要刪除任何東西。我記得我在那裡更改過程式碼後遇到了問題,花了很長時間才解決。
aHidd_PixFmt_BytesPerPixel:對於平面格式,這應該設定為多少?1?0?(- 深度)?我認為這對平面點陣圖來說是未定義的。讓我們將其設定為 0。我們只需要確保它不會破壞任何東西。
aHidd_PixFmt_Depth:這應該是平面的平面數。對於塊狀,這應該是 0 嗎?不,它在很多地方被用來確定顏色數量。我以前看到過另一種方式 - 結構體 BitMap 中的 Depth 是有效的 Plane[] 陣列元素的數量。在塊狀中,只有第一個是有效的,因此 Depth = 1。
當我呼叫 RTG(在本例中為任何非自定義晶片組驅動程式)Hidd_Gfx__Show(FALSE) 時,如何呼叫自定義晶片組驅動程式 Hidd_Gfx__Show(TRUE)?(反之亦然)。沒有這種關係。驅動程式彼此完全獨立。你可以同時使用兩個顯示器,一個在晶片組上,另一個在 GFX 板上。問題是,當選擇自定義晶片組模式時,必須有東西告訴 RTG 驅動程式變為閒置並啟用晶片組模式直通。這不是模擬特有的。
這需要在模擬中(以及無需在真正的 Amiga 上切換電纜)切換自定義/RTG 模式。好吧,你可以在載入任何其他驅動程式時讓 AROS 解除安裝晶片組驅動程式。在新增它時將 DDRV_BootMode 設定為 TRUE,你就完成了。晶片組驅動程式絕不能解除安裝,如果使用者執行專門需要晶片組模式的程式(例如舊遊戲或 whdload 或其他任何程式),它必須始終可用。
或者也許我們需要比 Show() 更強大的東西,這樣可能非顯示 RAM 點陣圖也會被釋放以降低記憶體使用量?Show() 僅顯示一個位圖。其他點陣圖會移出螢幕。有 ShowViewPorts(),它接受一個位圖列表。跟蹤其狀態取決於驅動程式。但是,你不能釋放任何點陣圖,AROS 可能會使用它們。只有建立者可以釋放點陣圖。晶片組顯示隱藏在“RTG 後面”(不可見),因為硬體(模擬或不模擬)認為 RTG 是當前活動的模式。
目前,任何嘗試開啟自定義晶片組模式都會在“RTG 模式”後面開啟它。你的意思是模擬問題嗎?模擬器是否嘗試在同一個視窗中顯示兩種模式?好吧,模擬很糟糕。為了克服這一點,你可以教驅動程式在沒有顯示任何內容時關閉模擬硬體(呼叫 Show(NULL))。這將告訴 UAE 關閉模擬的 RTG 顯示器。Windows 託管驅動程式在為了避免空視窗時也會做同樣的事情 - 它只是在視窗中沒有顯示任何內容時關閉顯示視窗。在真正的硬體上,這不是問題,反而是一個優勢。你可以使用兩種顯示器,並在它們上顯示不同的螢幕(由於不同的模式 ID)。問題是缺少 Show(NULL)。如果你的真實物理顯示器在你呼叫 Show(NULL) 時消失了,我會在 WinUAE 中實現它。事實上,在 LoadView() 期間,如果發生變化,每個驅動程式都將獲得 Show()。如果以前有內容在顯示,而現在消失了,驅動程式將獲得 Show(NULL)。它仍然與我的問題無關。RTG 和本機被視為不同的物理顯示器。(至少我們對此達成一致!)= 當本機螢幕上開啟某些內容(Native.Show(BitMap))時,沒有人會呼叫 RTG.Show(NULL)。我只想知道如何從另一個驅動程式的 Show() 方法(間接或直接)呼叫另一個驅動程式的(至少知道名稱)Show() 方法,以便兩者永遠不會同時處於活動狀態。乾淨地。如果我們想要某種愚蠢的類比,讓我們稱之為空白顯示而不是停用它或關閉它:)
順便說一下,自定義晶片組驅動程式的 ModeID 現在是正確的(不再生成假 ID)。那些具有自定義晶片組直通線纜和中繼或電子開關的真實物理 RTG 卡怎麼樣?這是 UAE 模擬的內容。不是兩個物理顯示器。換句話說:我們有一個共享兩個顯示器的單一顯示器,如果最上面的螢幕 = RTG 螢幕 -> RTG 啟用,如果最上面的螢幕 = 晶片組螢幕 -> RTG 停用,晶片組螢幕直通被啟用。這(完全)不支援。這是一個 hack,但這應該是這種情況下工作方式。我不在乎今天的設計方式是否奇怪或愚蠢,但 Picasso96 被設計為透過軟體自動支援直通,而某些卡(以及 UAE)支援並期望它。
可能存在“乾淨地”的問題。我能想到的 hack 是
a) 將兩個驅動程式程式碼放入一個 hidd 中,並執行大量的“if (native) else”
b) 新增一些兩個驅動程式都知道的虛擬模組,該模組將進行仲裁
graphics -> native.hidd (Show) -> module
模組檢查 rgt.hidd 是否之前已註冊
如果是
module-> rgt.hidd(Show(NULL))
然後
native.hidd-> module (註冊為已顯示)
native.hidd -> 繼續使用 Show
但是,我不確定從這個模組呼叫 Show(NULL) 是否安全
PS。對於螢幕拖動,你必須無論如何實現 ShowViewPorts
太難看了:)
你不能簡單地列舉所有顯示器並向除與當前 modeid 匹配的顯示器以外的所有顯示器傳送某種“節能”/“空白”訊號嗎?(然後在內部轉換為 Show(NULL)?)還是有某種 LoadView(MonitorID, NULL) 呼叫?我所知沒有 - 你的用例與系統設計有點衝突。到目前為止,假設是每個驅動程式例項將其“訊號”輸出到單獨的物理顯示裝置,並且驅動程式不知道彼此的存在,而在你的情況下,兩個獨立的驅動程式需要輸出到一個物理顯示裝置,但永遠不會同時輸出。除非你想要重新設計圖形驅動程式系統的執行方式,否則你必須使用類似 b) 的“方法”。
難道不能在 intuition.library/graphics.library 中實現,讓它們跟蹤同一個顯示器和不同顯示器上的顯示器,並在同一個顯示器上的一個驅動程式優先於另一個驅動程式時傳送 Show(NULL) 嗎?這可能是“正確”的解決方案,但我不會請求(可能是複雜的)新核心功能,該功能只有 (?) m68k-amiga(使用 RTG)需要。
Amiga 硬體上的自動顯示器切換是一個正常功能,應該由 AROS 正確支援;而不是 hack。
我們有兩類顯示裝置:驅動程式和顯示器。顯示器描述允許的顯示模式時序(但不包括顏色深度)。驅動程式連線到顯示器,並使用顯示器的時序列表來確定其所有可能模式中的哪些模式有效。多個驅動程式可以連線到單個顯示器例項,以表示直通系統。
讓我們想象一臺 A4000,它配備了一張 Picasso96 風格的卡,以及一張獨立的(ATI Mach64)卡,位於 PCI 匯流排板上,還有兩個顯示器,一個 1084 和一個標準 VGA
Driver 1 (P96) \
---> Monitor 1 (Commodore 1084)
Driver 2 (AGA) /
Driver 3 (ATI) ----> Monitor 2 (VGA)
在這種情況下,我們需要Toni提到的P96和AGA的“blanking”行為。現在,假設有人(比如我)為Voodoo 1 3D卡編寫了一個驅動程式,該卡具有VGA直通功能,並將它放入A4000中。
Driver 1 (P96) \
---> Monitor 1 (Commodore 1084)
Driver 2 (AGA) /
Driver 3 (ATI) \
---> Monitor 2 (VGA)
Driver 4 (Voodoo) /
在這種情況下,我們也需要blanking行為。順便說一下,Voodoo的情況也適用於i386。
當某個程式在本地螢幕上開啟時(Native.Show(BitMap)),沒有人會呼叫RTG.Show(NULL)。
這是錯誤的。所有驅動程式在LoadView()期間都會得到一些東西。當驅動程式擁有一個螢幕,並且這個螢幕關閉時,驅動程式會得到Show(NULL)。至少應該如此。如果這種情況沒有發生,那就是一個bug。參見driver_LoadView()例程。
或者你指的是你擁有兩個螢幕,一個在主機板上,另一個在晶片組上,然後試圖對它們進行深度排列的情況?嗯……系統並不真正支援這種情況。看起來驅動程式需要以某種方式知道它的螢幕在晶片組的屏幕後面。沒錯。(或者反過來,選擇具有當前最上面螢幕的“顯示器”很重要)。
可以在不進行hack的情況下實現它。但是,要做到這一點,必須滿足兩個條件
1. 驅動程式需要知道正在顯示的ViewPort。
2. 晶片組驅動程式需要為其ViewPort填充銅列表指標。
我想,(2) 可以透過向圖形HIDD新增MakeVPort方法來完成。(1)... 還不確定。也許ShowViewPort()不好。如果滿足這兩個條件,RTG驅動程式可以檢查GfxBase->View,並檢查其ViewPort是否在晶片組ViewPort的後面或前面。只有晶片組ViewPort的銅列表指標非零。
r38178 "如果回撥返回錯誤,立即中斷" 測試會導致使用UAEGFX時,m68k-amiga上的空白螢幕,因為晶片組mdd先執行,fn()返回零,然後導致後續驅動程式(UAEGFX)始終被跳過。移除測試可以讓UAEGFX再次工作。(錯誤測試?成功 == 0,而不是錯誤,至少driver_LoadViewPorts()在成功時返回零)。當然,0 代表沒有錯誤,這是一個bug。移除感嘆號。
當RTG可用時,我希望為引導選單和初始WB螢幕選擇一個漂亮的640x480x8或類似的模式(而不是無聊的640x256x2,OCS/ECS上的hires和4平面非常慢)。
可能過於醜陋的方法是遮蔽模式ID中的顯示器ID部分,並檢查它是否非零。不幸的是,DPIF_IS標誌似乎沒有用。
你可以看看cgx中IsCyberModeId()是如何實現的。OOP_Object *pf = (OOP_Object *)info.reserved[1]; 是的,我認為這也不是正確的方法。但是,我認為這並不是一個合適的方法。這並不能阻止BestModeID()選擇晶片組模式。需要發明一些東西。“其他”類似Amiga的作業系統是否有某種DPIF_CHUNKY或類似的標誌?令人討厭的是,有DPIF_AA和DPIF_ECS,但沒有DPIF_OCS或類似的標誌。我希望在ROM程式碼中有一種快速簡潔的方式來檢測模式ID型別。(用於選擇“最佳”引導選單和初始外殼模式,早期預警?在螢幕開啟之前)。
/*
* Set the propertyflags,
* Note that we enforce some flags because we emulate these features by software
* DIPF_IS_FOREIGN is actually set only by Picasso96 and only for modes that are
* not graphics.library compatible. Many m68k RTG games rely on this flag not being
* set.
*/
di->PropertyFlags = DIPF_IS_WB | DIPF_IS_SPRITES | DIPF_IS_DBUFFER
| HIDDProps.DisplayInfoFlags;
我認為這應該移到HIDD_Gfx_ModeProperties()中,這樣就可以被自定義晶片組驅動程式覆蓋。這些標誌是故意強制用於由graphics.library模擬的功能的。SPRITES被設定,因為graphics.library可以模擬滑鼠精靈。WB被設定... 為什麼不呢?DBUFFER被設定,因為我模擬了它。我知道,模擬很糟糕,實際上應該在驅動程式中處理它。
不應該在特殊的自定義晶片組模式(HAM等)中設定DIPF_IS_WB。(HAM,等等)。另外,似乎在Amiga RTG本機模式中,DIPF_IS_DBUFFER沒有被設定。我還沒有 100% 確認,但是如果這是真的,那麼一些(愚蠢的)軟體肯定會假設 DIPF_IS_DBUFFER 設定 = 始終是晶片組模式。
- 移除DBUFFER強制。
- 向ModeProperties新增一個欄位,例如ResetFlags。它將包含在預設標誌集中需要重置的位。如果在那裡設定了DIPF_IS_WB,它將在結果標誌集中被取消設定。這將提供與已完成工作的良好的向後相容性。
你怎麼看,如果我們不按ID號排序驅動程式,而是按優先順序排序?如果我們為晶片組驅動程式分配-128,為其他驅動程式分配0,那麼在兩個引數相同的模式中,BestModeID()將選擇優先順序更高的那個。但是,如果我們請求320x256,它不會被提升到RTG,即使RTG驅動程式只提供320x200和640x480。PAL 320x256 仍然是最匹配的。Amiga本機模式提升非常簡單,BestModeID()只返回RTG模式。它永遠不會返回晶片組模式(至少在不使用一些配置程式的情況下)。這樣,不帶模式ID的OpenScreen()始終獲得RTG模式,唯一獲得所需模式(包括晶片組模式)的方法是指定所需的ModeID。320x256將返回一個更大的東西(在最壞的情況下可能是320x400)。這仍然是預期的結果。
因此,簡單的優先順序無法完全解決這個問題。一種可能的選項是向AddDisplayDriverA()新增一個“不要自動選擇我”標誌。另一個選項是允許使用者在首選項中選擇一個首選顯示器,BestModeIDA()應該首先嚐試這個顯示器,並且只有在沒有找到任何東西的情況下才嘗試其他顯示器。
BestModeID()選項可能是最好的,至少對於共享顯示器的情況來說是最好的。
模式提升無論如何都需要可配置,因此首選顯示器可能是最符合Amiga相容性的方式。我不確定它是否非常適合AROS設計。m68k-amiga 目前已經覆蓋了 BestModeID()(直到有更好的解決方案),它簡單地首先查詢 RTG 模式,並且只有在 RTG 模式掃描沒有返回任何結果的情況下才會檢查晶片組模式。似乎工作正常。
我認為我們有略微不同的用例,應該由驅動程式程式碼處理
- 單個顯示器,單個驅動程式。始終按預期工作。
- 單個顯示器,多個驅動程式。這裡應該將一個配置為“主驅動程式”,BestModeID()只返回它為主驅動程式模式的模式。
- 多個顯示器,每個顯示器一個驅動程式。在這種情況下需要優先順序嗎?BestModeID()應該從任何顯示器返回模式,還是隻從某種“首選顯示器”返回模式?
- 多個顯示器,每個顯示器一個或多個驅動程式。(這是存在的嗎?也許是m68k-amiga和兩張RTG卡,只有一張有直通功能?)不確定在這裡該怎麼做,或者這是否值得麻煩。
但這需要將圖形驅動程式和顯示器分開。也許這變得太複雜了。
對RTG驅動程式進行快速hack,允許RTG/本機切換,可能過於醜陋,但至少似乎有效,並且允許更容易測試。我注意到在RTG/晶片組螢幕之間切換時,存在奇怪的副作用。僅對塊狀驅動程式強制執行上述標誌。對於平面驅動程式,它們需要由驅動程式提供。背後的理念:任何RTG螢幕都與WB相容。但並非每個平面螢幕都相容。
啟動到Wanderer(RTG模式),執行任何專門需要PAL或NTSC自定義晶片組螢幕的程式。模式按預期切換(RTG晶片組直通啟用),但晶片組螢幕的選單欄和滑鼠游標不見了,輸入(滑鼠和鍵盤)仍然傳送到Wanderer的視窗。缺少自動螢幕啟用。當螢幕上的某個視窗被啟用時,輸入將被切換。ActiveScreen 在 ActivateWindow() 中,但為什麼這個問題只發生在“顯示器”之間切換時?如果只使用RTG或只使用晶片組螢幕,螢幕切換工作正常。活動視窗不會改變。它只會在你點選最前面螢幕上的另一個視窗時才會改變。滑鼠精靈只在活動顯示器上可見。活動顯示器是顯示活動螢幕的顯示器。活動顯示器只有在螢幕設定為最上面時才會被設定(快捷鍵和深度小部件只將螢幕設定為底部),而 OpenScreen() 只有在沒有設定顯示器時才會設定活動顯示器。Intuition 跟蹤當前活動顯示器。當螢幕被髮送到底部時,新的活動螢幕不是列表的首部。它是第一個與當前顯示器匹配的螢幕。活動顯示器在以下情況下會改變
1. Some screen is explicitly set frontmost by some software. 2. There was no active monitor at all (all screens blank). 3. Hosted driver calls a special activation callback (see monitorclass source). 4. Mouse pointer crosses screen borders and spatial linkage for the current monitor is set up in monitorclass.
(4) 是一個TODO,還沒有實現,但應該實現。
我是否只需在構建m68k版本時新增臨時#ifdef來始終設定活動顯示器?(缺少ActiveMonitor()呼叫使得開發和測試非常煩人,因此任何形式的臨時hack都比沒有好)。如果你想,你可以玩啟用回撥。它們在原生驅動程式上可以完美執行。RTG驅動程式需要在關閉直通時呼叫它。唯一的瓶頸 - 晶片組驅動程式需要在RTG驅動程式釋放直通時呼叫它。它們需要以某種方式進行通訊。另一種方法:向monitorclass屬性新增描述共享相同顯示器的驅動程式的屬性(類似於當前空間連結,類似於當前空間連結)。讓Intuition跟蹤它。
如果我透過按下Amiga+N/M或點選Wanderer的螢幕深度小部件來切換螢幕,也會發生相同的事情。
整個getdisplayinfodata.c應該擴充套件以支援自定義晶片組的特殊功能(最重要的功能是過掃描和精靈解析度與顯示解析度不同)。還有很多東西缺失。這就是我們在ModeProperties結構中新增size的原因。它可以擴充套件。
在任何圖形操作(文字輸出、滾動、對話方塊)等期間,都會有大量FindName("hidd.graphics.gc")呼叫。這是由於OOP存根的工作方式造成的。在非ROMmable庫中(AROS_CREATE_ROM未定義),它們將該查詢的結果快取在.bss中。在ROMmable庫中,沒有.bss。確實需要找到一種方法,讓它在ROMmable庫中工作,而不會出現所有這些開銷。
實現了一個MakeVPort()和MrgCop()的API。
- MrgCop()在構建ViewPortData鏈後呼叫PrepareViewPorts。該方法還會獲取View指標。你可以在那裡進行任何準備工作。
- ShowViewPort的工作只是提交計算出的更改。
由於你獲得了View,你可以檢測你的ViewPortData在它中的位置。你也可以在這兩個方法中管理AmigaOS銅列表指標。fakegfxhidd(軟體滑鼠游標)是否也可以支援ShowViewPorts()?不需要合成/多個ViewPort,只需要獲取View資訊。
因為fakegfxhidd只支援Show(),所以沒有辦法(至少在不進行非常醜陋的hack的情況下)處理RTG/晶片組直通,而且大多數UAE版本沒有Picasso96(UAEGFX)硬體滑鼠游標模擬。(據我所知,它沒有從WinUAE移植,而WinUAE只在Direct3D模式下支援它,而Direct3D模式並不意味著與太舊的PC相容)。
也許我可以向uaegfx驅動程式新增軟體游標模擬,但我不知道是否值得麻煩。(或者這是正確的做法?)
今天,我讓planarbm更快更好了。現在它只在內部包含struct BitMap。不再有平面陣列等複製,你可以隨時獲取指向它的指標,以便進行直接修改,現在我正在研究軟體合成層。想要將其泛化。它將是一個獨立的模組,位於DEVS:Monitors中。它將熱插拔到graphics.library。你可以更新Amiga顯示驅動程式以支援它。而不是呼叫GetBitMap(它會複製結構),只需獲取aHidd_PlanarBM_BitMap屬性即可。這類似於aHidd_ChunkyBM_Buffer。它是可點燃和可設定的,所以你可以將自己的點陣圖包裝到物件中。我還發明瞭一個用於映象顯示驅動程式(如VESA和VGA)的框架。基類將自行支援所有功能。你只需要向它提供一個單幀緩衝區點陣圖。它會自行映象,消除程式碼重複。
當請求Amiga驅動程式建立新的點陣圖時,就會發生這種情況,我不明白它與GetBitMap/SetBitMap及其同類函式有什麼關係。(至少這個問題不是這樣)。AmigaVideoBM__Root__New() 被呼叫,然後立即呼叫 OOP_DoSuperMethod -> BM_New -> PBM_New -> 失敗。
Amiga驅動程式不是很乾淨,而且對於任何有用的事情來說,它仍然太慢了。例如,PutImage() 需要彙編C2P和GetImage() P2C例程,目前它們太慢了^10。
新增RTG驅動程式支援,但晶片組對於軟體合成來說太慢了。正常的全硬體螢幕拖動將在某一天完成(目前,拖動時只有最前面的螢幕可見)。
為什麼許多圖形例程使用 LONG 座標?是否有可能用 WORD 或平臺特定的 16/32 位 typedef 來代替它們?這會導致在 68000 相容的構建中出現不必要的減速,因為它可能會強制使用更慢的 32 位乘法(32x32=32)和除法(32/32=32),而這些操作不受 68000/010 的直接支援。(68000/010 只有 16x16=32 乘法和 32/16=16:16 除法指令),此外,在這些 CPU 上,所有 LONG 操作始終比 WORD 操作慢(68000/010 ALU 是 16 位的)。
所有圖形例程 :)(例如,包括 hidds/graphics/BM_Class.c)Graphics.library 函式引數文件沒有太多意義.. clib/protos 將大多數函式列為接受 LONG(即使 Move 和 Draw 使用 RastPort WORD 欄位來儲存最後位置!)Autodocs 將大多數函式列為接受 WORD。
在內部,AOS graphics.library 似乎總是使用 WORD(忽略高 16 位,因此對於暫存器引數來說很容易)。這可能太遲了,但我不知道為什麼 AROS 從未定義 "虛擬暫存器",這將允許呼叫者將 <小於暫存器寬度的任何內容> 寫入 <該體系結構上具有預定義寬度的任何暫存器>,然後在庫函式端提取 <任何預期的寬度> 用於本地使用。
- 虛擬暫存器是 64 位寬
- 呼叫程式碼寫入一個無符號的 32 位值
- 被呼叫程式碼獲取低 16 位
- 被呼叫程式碼將它放入本地無符號的 16 位副本中並使用它
在 68k 上,它可能大多是無操作的,而在其他體系結構上則是其他操作。
graphics.library API 宣告與 OS3.1 相容。如果問題涉及它們,我會在內部將它們強制轉換為 WORD。至於 graphics.hidd... 好吧,我個人不反對更改為 WORD(不過,據我所知,座標在那裡是 WORD)。
amiga-m68k 最大的遊戲相容性問題是 "錯誤的"(類似 RTG 的)結構點陣圖格式用於平面螢幕,許多系統友好的(即不接管系統)遊戲會以正常方式開啟螢幕,然後直接寫入螢幕的點陣圖。如何解決這個問題?我注意到已經有了支援(至少是部分支援),例如 IS_HIDD_BM 和 OBTAIN_HIDD_BM 之類的宏。
graphics.hidd 中沒有一個 PlanarBM 類,它基本上是一個記憶體中的點陣圖實現,允許訪問其資料行嗎?可能,但應用程式可見的結構點陣圖仍然是 BMF_SPECIALFMT。我的測試是 Dune II 遊戲,它只顯示紅色滑鼠游標和空白螢幕。(它還會在正確呼叫 LoadRGB4() 之前,用 NULL 視窗呼叫 LoadRGB4()。)只需檢查螢幕的結構點陣圖標誌欄位和平面指標嗎?與真正的平面指標相比,BMF_SPECIALFMT "平面指標" 顯得相當隨機,並沒有指向晶片 RAM(如果可用的話)。