Commit 94ffeea7 authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Add support for new GraphicsV_VetMode2 call

Detail:
  VetMode2 allows the driver to give the OS extra feedback about a proposed mode. In particular, it allows the driver to suggest a value for the ExtraBytes control list item, so by using the VetMode2 call ScreenModes is able to support modes where the video driver requires extra padding to be added to the framebuffer.
  h/modex - Remove local definitions of control list item numbers. Reserve space for one extra control list item in the VIDCList structure.
  c/ScrModes - Use Global/VIDCList.h for control list item numbers. Update mode_valid to make use of VetMode2 where available, and give it the ability to copy the resulting VIDCList into a caller-supplied buffer, allowing service_modeextension to easily use the correct ExtraBytes setting.
Admin:
  Tested on Raspberry Pi 3
  Requires Kernel-5_82


Version 0.65. Tagged as 'ScrModes-0_65'
/* (0.64)
/* (0.65)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.64
#define Module_MajorVersion_CMHG 0.65
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 01 May 2017
#define Module_Date_CMHG 07 Jun 2017
#define Module_MajorVersion "0.64"
#define Module_Version 64
#define Module_MajorVersion "0.65"
#define Module_Version 65
#define Module_MinorVersion ""
#define Module_Date "01 May 2017"
#define Module_Date "07 Jun 2017"
#define Module_ApplicationDate "01-May-17"
#define Module_ApplicationDate "07-Jun-17"
#define Module_ComponentName "ScrModes"
#define Module_ComponentPath "castle/RiscOS/Sources/Video/UserI/ScrModes"
#define Module_FullVersion "0.64"
#define Module_HelpVersion "0.64 (01 May 2017)"
#define Module_LibraryVersionInfo "0:64"
#define Module_FullVersion "0.65"
#define Module_HelpVersion "0.65 (07 Jun 2017)"
#define Module_LibraryVersionInfo "0:65"
......@@ -35,6 +35,7 @@
#include "Global/OsBytes.h"
#include "Global/CMOS.h"
#include "Global/ModHand.h"
#include "Global/VIDCList.h"
#undef Module_Title /* CMHG defines this too */
#include "Interface/HighFSI.h"
#include "Interface/ScrModes.h"
......@@ -502,7 +503,10 @@ static int current_graphicsv_driver(void)
return variables[0];
}
static void build_a_vidclist(VIDCListRef vp, ModeDescriptionRef mp, const PixelFormatRef pf)
/* Build a VIDC list
* Returns the number of control list items
*/
static int build_a_vidclist(VIDCListRef vp, ModeDescriptionRef mp, const PixelFormatRef pf)
{
int fn;
int ctrllistpos = 0;
......@@ -521,17 +525,17 @@ static void build_a_vidclist(VIDCListRef vp, ModeDescriptionRef mp, const PixelF
/* Only specify ModeFlags & NColour if necessary? */
if (!is_old_format(pf))
{
vp->vcparam[ctrllistpos].index = NCOLOUR_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_NColour;
vp->vcparam[ctrllistpos].value = pf->ncolour;
ctrllistpos++;
vp->vcparam[ctrllistpos].index = MODEFLAGS_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_ModeFlags;
vp->vcparam[ctrllistpos].value = pf->modeflags;
ctrllistpos++;
}
if (current_monitor->dpms_state != -1)
{
vp->vcparam[ctrllistpos].index = DPMS_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_DPMSState;
vp->vcparam[ctrllistpos].value = current_monitor->dpms_state;
ctrllistpos++;
}
......@@ -539,58 +543,63 @@ static void build_a_vidclist(VIDCListRef vp, ModeDescriptionRef mp, const PixelF
if (current_monitor->lcd_support != 0)
{
IFDEBUG printf("I'm an LCD panel & I'm going to tell the Kernel!\n");
vp->vcparam[ctrllistpos].index = LCDMODE_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_LCDMode;
vp->vcparam[ctrllistpos].value = LCDMODE_VALUE;
ctrllistpos++;
if (current_monitor->lcd_support != 3)
{
vp->vcparam[ctrllistpos].index = LCDDUAL_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_LCDDualPanelMode;
vp->vcparam[ctrllistpos].value = LCDDUAL_VALUE;
ctrllistpos++;
}
vp->vcparam[ctrllistpos].index = LCDOFF0_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_LCDOffset0;
vp->vcparam[ctrllistpos].value = LCDOFF0_VALUE;
ctrllistpos++;
vp->vcparam[ctrllistpos].index = LCDOFF1_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_LCDOffset1;
vp->vcparam[ctrllistpos].value = LCDOFF1_VALUE;
ctrllistpos++;
vp->vcparam[ctrllistpos].index = DACCTRL_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_DACControl;
vp->vcparam[ctrllistpos].value = DACCTRL_VALUE;
ctrllistpos++;
}
if (mp->definition.timings.external_clock != -1)
{
vp->vcparam[ctrllistpos].index = HCLK_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_HClockSelect;
vp->vcparam[ctrllistpos].value = mp->definition.timings.external_clock;
ctrllistpos++;
}
if (mp->definition.timings.interlaced)
{
vp->vcparam[ctrllistpos].index = INTERLACED_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_Interlaced;
vp->vcparam[ctrllistpos].value = 1;
ctrllistpos++;
}
if (current_monitor->output_format != -1)
{
vp->vcparam[ctrllistpos].index = OPFORMAT_INDEX;
vp->vcparam[ctrllistpos].index = ControlList_OutputFormat;
vp->vcparam[ctrllistpos].value = current_monitor->output_format;
ctrllistpos++;
}
vp->vcparam[ctrllistpos].index = -1; /* List terminator */
return ctrllistpos;
}
/* Test for whether a given mode definition is usable within the
* specified data rate and video memory size bounds, at a given pixel
* depth. Limitations of the current video controller chip (if known)
* are also factored in to the test.
* If the mode is valid, it optionally copies the VIDC list into the
* provided buffer.
*/
static int mode_valid(ModeDescriptionRef mp, const PixelFormatRef pf,
uint32_t maxdatarate /* kB/s */,
uint32_t maxdatasize /* bytes */)
uint32_t maxdatasize /* bytes */,
VIDCListRef outlist)
{
_kernel_swi_regs r;
VIDCList vetlist;
......@@ -670,18 +679,55 @@ static int mode_valid(ModeDescriptionRef mp, const PixelFormatRef pf,
}
/* Propose the resulting mode to the graphics driver */
build_a_vidclist(&vetlist, mp, pf);
int ctrllistpos = build_a_vidclist(&vetlist, mp, pf);
r.r[0] = (int)&vetlist;
r.r[1] = NULL;
r.r[4] = GraphicsV_VetMode | (driver<<24);
r.r[1] = 0; /* Flags */
r.r[4] = GraphicsV_VetMode2 | (driver<<24);
r.r[9] = GraphicsV;
_kernel_swi(OS_CallAVector, &r, &r);
if ((r.r[4] == 0) && (r.r[0] != 0))
if ((r.r[4] == 0) && !(r.r[0] & ~7)) /* Call claimed, and no unknown flags returned? */
{
return 0; /* Had a definitive answer from GraphicsV that it no-likey */
if ((r.r[0] & GVVetMode2_ResultMask) == 0)
{
return 0; /* Had a definitive answer from GraphicsV that it no-likey */
}
else if (r.r[0] & GVVetMode2_ExtraBytes_Invalid)
{
/* Check to see if this ExtraBytes value will cause us to exceed
* maxdatasize.
* (n.b. it's assumed that build_a_vidclist will never set
* ExtraBytes itself)
*/
datasize += r.r[2] * my;
if (datasize > maxdatasize)
{
return 0;
}
/* ExtraBytes value is acceptable, use it */
vetlist.vcparam[ctrllistpos].index = ControlList_ExtraBytes;
vetlist.vcparam[ctrllistpos].value = r.r[2];
ctrllistpos++;
vetlist.vcparam[ctrllistpos].index = -1; /* List terminator */
}
}
else
{
/* Try the old vet call */
r.r[0] = (int)&vetlist;
r.r[1] = NULL;
r.r[4] = GraphicsV_VetMode | (driver<<24);
_kernel_swi(OS_CallAVector, &r, &r);
if ((r.r[4] == 0) && (r.r[0] != 0))
{
return 0; /* Had a definitive answer from GraphicsV that it no-likey */
}
}
/* No obvious conflicts, accept the mode */
if (outlist != NULL)
{
*outlist = vetlist;
}
return 1;
}
......@@ -716,7 +762,7 @@ bool find_deepest_by_xyhz(PixelFormatRef fp, ModeDescriptionRef mp)
*/
while (pflistlen)
{
if (mode_valid(mp, pflist, INT32_MAX, INT32_MAX))
if (mode_valid(mp, pflist, INT32_MAX, INT32_MAX, NULL))
{
/* That depth is achievable, keep it if bigger */
if (pflist->log2bpp > maxlog2bpp)
......@@ -897,13 +943,11 @@ static void service_modeextension(_kernel_swi_regs *regs)
{
/* Test whether this mode can satisfy the requirements */
if ((sel->framerate == -1 || sel->framerate == mp->frame_hz) &&
mode_valid(mp, &pf, dataratelimit, datasizelimit))
mode_valid(mp, &pf, dataratelimit, datasizelimit, &thevidclist))
{
build_a_vidclist(&thevidclist, mp, &pf); /* use the local static structure */
/* And claim the service */
regs->r[1] = 0; /* Service_Serviced */
regs->r[3] = (int)&thevidclist; /* return pointer to VIDC list to use */
regs->r[3] = (int)&thevidclist; /* return pointer to VIDC list to use (mode_valid will have filled this in for us) */
regs->r[4] = NULL; /* marks no workspace list(mode selector given) */
return;
}
......@@ -948,7 +992,7 @@ static void service_enumeratescreenmodes(_kernel_swi_regs *regs)
for (;;)
{
if (!mode_valid(mp, pf, dataratelimit, datasizelimit))
if (!mode_valid(mp, pf, dataratelimit, datasizelimit, NULL))
{
/* TMD 03-Nov-93: Fix bug MED-00833
* Code used to set depth to 5 here, assuming that if the mode
......@@ -1063,7 +1107,7 @@ static int mode_available(uint32_t xres, uint32_t yres, const PixelFormatRef pf,
do
{
if ((framerate == -1 || framerate == mp->frame_hz) &&
mode_valid(mp, pf, INT32_MAX, INT32_MAX))
mode_valid(mp, pf, INT32_MAX, INT32_MAX, NULL))
{
return 1;
}
......@@ -1466,7 +1510,6 @@ void ScreenModes_servicecall(int servicecallno, _kernel_swi_regs *regs, void *pw
_kernel_oserror *ScreenModes_cmdhandler(const char *arg_string, int argc, int cmd_no, void *pw)
{
_kernel_oserror *result;
int display = 0;
switch (cmd_no)
{
......
......@@ -79,25 +79,13 @@
*/
/**Added by WT 13-1-95 for Stork **/
#define LCDMODE_INDEX 01
#define LCDMODE_VALUE 1 /*Enable*/
#define LCDDUAL_INDEX 02
#define LCDDUAL_VALUE 1 /*Enable*/
#define LCDOFF0_INDEX 03
#define LCDOFF0_VALUE 6 /*Defining a 640x480 dual-panel LCD as used in Stork*/
#define LCDOFF1_INDEX 04
#define LCDOFF1_VALUE 129 /*Defining a 640x480 dual-panel LCD as used in Stork*/
#define DACCTRL_INDEX 06
#define DACCTRL_VALUE 1 /*Enable - testing only*/
/**End of additions**/
#define HCLK_INDEX 9
#define DPMS_INDEX 11
#define INTERLACED_INDEX 12
#define OPFORMAT_INDEX 13
#define NCOLOUR_INDEX 15
#define MODEFLAGS_INDEX 16
/* Pixel format representation used by GraphicsV */
typedef struct
{
......@@ -132,7 +120,7 @@ typedef struct
uint32_t vpar[FR__COUNT]; /* vertical parameters */
uint32_t pixelrate; /* pixel rate measured in kHz */
uint32_t syncpol; /* sync polarity code, 0..3 */
ModeParam vcparam[12]; /* Holds VCparameters: LCD mode, LCD dual-panel, LCD offsets(2), DAC control, -1
ModeParam vcparam[13]; /* Holds VCparameters: LCD mode, LCD dual-panel, LCD offsets(2), DAC control, ExtraBytes, -1
* with optional NColour, ModeFlags, DPMS, HCLK Interlaced and/or output_format fields
*/
} VIDCList, *VIDCListRef;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment