vaseboot/VasEBoot-core/video/video.c

762 lines
23 KiB
C

/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
*
* VasEBoot is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VasEBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/video.h>
#include <VasEBoot/types.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/i18n.h>
VasEBoot_MOD_LICENSE ("GPLv3+");
/* The list of video adapters registered to system. */
VasEBoot_video_adapter_t VasEBoot_video_adapter_list = NULL;
/* Active video adapter. */
VasEBoot_video_adapter_t VasEBoot_video_adapter_active;
/* Restore back to initial mode (where applicable). */
VasEBoot_err_t
VasEBoot_video_restore (void)
{
if (VasEBoot_video_adapter_active)
{
VasEBoot_video_adapter_active->fini ();
if (VasEBoot_errno != VasEBoot_ERR_NONE)
return VasEBoot_errno;
VasEBoot_video_adapter_active = 0;
}
return VasEBoot_ERR_NONE;
}
/* Get information about active video mode. */
VasEBoot_err_t
VasEBoot_video_get_info (struct VasEBoot_video_mode_info *mode_info)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
/* If mode_info is NULL just report that video adapter is active. */
if (! mode_info)
{
VasEBoot_errno = VasEBoot_ERR_NONE;
return VasEBoot_errno;
}
return VasEBoot_video_adapter_active->get_info (mode_info);
}
VasEBoot_video_driver_id_t
VasEBoot_video_get_driver_id (void)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_VIDEO_DRIVER_NONE;
return VasEBoot_video_adapter_active->id;
}
/* Get information about active video mode. */
VasEBoot_err_t
VasEBoot_video_get_info_and_fini (struct VasEBoot_video_mode_info *mode_info,
void **framebuffer)
{
VasEBoot_err_t err;
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
err = VasEBoot_video_adapter_active->get_info_and_fini (mode_info, framebuffer);
if (err)
return err;
VasEBoot_video_adapter_active = 0;
return VasEBoot_ERR_NONE;
}
/* Determine optimized blitting formation for specified video mode info. */
enum VasEBoot_video_blit_format
VasEBoot_video_get_blit_format (struct VasEBoot_video_mode_info *mode_info)
{
/* Check if we have any known 32 bit modes. */
if (mode_info->bpp == 32)
{
if ((mode_info->red_mask_size == 8)
&& (mode_info->red_field_pos == 16)
&& (mode_info->green_mask_size == 8)
&& (mode_info->green_field_pos == 8)
&& (mode_info->blue_mask_size == 8)
&& (mode_info->blue_field_pos == 0))
{
return VasEBoot_VIDEO_BLIT_FORMAT_BGRA_8888;
}
else if ((mode_info->red_mask_size == 8)
&& (mode_info->red_field_pos == 0)
&& (mode_info->green_mask_size == 8)
&& (mode_info->green_field_pos == 8)
&& (mode_info->blue_mask_size == 8)
&& (mode_info->blue_field_pos == 16))
{
return VasEBoot_VIDEO_BLIT_FORMAT_RGBA_8888;
}
}
/* Check if we have any known 24 bit modes. */
else if (mode_info->bpp == 24)
{
if ((mode_info->red_mask_size == 8)
&& (mode_info->red_field_pos == 16)
&& (mode_info->green_mask_size == 8)
&& (mode_info->green_field_pos == 8)
&& (mode_info->blue_mask_size == 8)
&& (mode_info->blue_field_pos == 0))
{
return VasEBoot_VIDEO_BLIT_FORMAT_BGR_888;
}
else if ((mode_info->red_mask_size == 8)
&& (mode_info->red_field_pos == 0)
&& (mode_info->green_mask_size == 8)
&& (mode_info->green_field_pos == 8)
&& (mode_info->blue_mask_size == 8)
&& (mode_info->blue_field_pos == 16))
{
return VasEBoot_VIDEO_BLIT_FORMAT_RGB_888;
}
}
/* Check if we have any known 16 bit modes. */
else if (mode_info->bpp == 16)
{
if ((mode_info->red_mask_size == 5)
&& (mode_info->red_field_pos == 11)
&& (mode_info->green_mask_size == 6)
&& (mode_info->green_field_pos == 5)
&& (mode_info->blue_mask_size == 5)
&& (mode_info->blue_field_pos == 0))
{
return VasEBoot_VIDEO_BLIT_FORMAT_BGR_565;
}
else if ((mode_info->red_mask_size == 5)
&& (mode_info->red_field_pos == 0)
&& (mode_info->green_mask_size == 6)
&& (mode_info->green_field_pos == 5)
&& (mode_info->blue_mask_size == 5)
&& (mode_info->blue_field_pos == 11))
{
return VasEBoot_VIDEO_BLIT_FORMAT_RGB_565;
}
}
else if (mode_info->bpp == 1)
return VasEBoot_VIDEO_BLIT_FORMAT_1BIT_PACKED;
/* Backup route. Unknown format. */
/* If there are more than 8 bits per color, assume RGB(A) mode. */
if (mode_info->bpp > 8)
{
if (mode_info->reserved_mask_size > 0)
{
return VasEBoot_VIDEO_BLIT_FORMAT_RGBA;
}
else
{
return VasEBoot_VIDEO_BLIT_FORMAT_RGB;
}
}
/* Assume as indexcolor mode. */
return VasEBoot_VIDEO_BLIT_FORMAT_INDEXCOLOR;
}
/* Set new indexed color palette entries. */
VasEBoot_err_t
VasEBoot_video_set_palette (unsigned int start, unsigned int count,
struct VasEBoot_video_palette_data *palette_data)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->set_palette (start, count, palette_data);
}
/* Get indexed color palette entries. */
VasEBoot_err_t
VasEBoot_video_get_palette (unsigned int start, unsigned int count,
struct VasEBoot_video_palette_data *palette_data)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->get_palette (start, count, palette_data);
}
/* Set viewport dimensions. */
VasEBoot_err_t
VasEBoot_video_set_viewport (unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->set_viewport (x, y, width, height);
}
/* Get viewport dimensions. */
VasEBoot_err_t
VasEBoot_video_get_viewport (unsigned int *x, unsigned int *y,
unsigned int *width, unsigned int *height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->get_viewport (x, y, width, height);
}
/* Set region dimensions. */
VasEBoot_err_t
VasEBoot_video_set_region (unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->set_region (x, y, width, height);
}
/* Get region dimensions. */
VasEBoot_err_t
VasEBoot_video_get_region (unsigned int *x, unsigned int *y,
unsigned int *width, unsigned int *height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->get_region (x, y, width, height);
}
/* Set status of the intersection of the viewport and the region. */
VasEBoot_err_t
VasEBoot_video_set_area_status (VasEBoot_video_area_status_t area_status)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->set_area_status (area_status);
}
/* Get status of the intersection of the viewport and the region. */
VasEBoot_err_t
VasEBoot_video_get_area_status (VasEBoot_video_area_status_t *area_status)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->get_area_status (area_status);
}
/* Map color name to adapter specific color. */
VasEBoot_video_color_t
VasEBoot_video_map_color (VasEBoot_uint32_t color_name)
{
if (! VasEBoot_video_adapter_active)
return 0;
return VasEBoot_video_adapter_active->map_color (color_name);
}
/* Map RGB value to adapter specific color. */
VasEBoot_video_color_t
VasEBoot_video_map_rgb (VasEBoot_uint8_t red, VasEBoot_uint8_t green, VasEBoot_uint8_t blue)
{
if (! VasEBoot_video_adapter_active)
return 0;
return VasEBoot_video_adapter_active->map_rgb (red, green, blue);
}
/* Map RGBA value to adapter specific color. */
VasEBoot_video_color_t
VasEBoot_video_map_rgba (VasEBoot_uint8_t red, VasEBoot_uint8_t green, VasEBoot_uint8_t blue,
VasEBoot_uint8_t alpha)
{
if (! VasEBoot_video_adapter_active)
return 0;
return VasEBoot_video_adapter_active->map_rgba (red, green, blue, alpha);
}
/* Unmap video color back to RGBA components. */
VasEBoot_err_t
VasEBoot_video_unmap_color (VasEBoot_video_color_t color, VasEBoot_uint8_t *red,
VasEBoot_uint8_t *green, VasEBoot_uint8_t *blue,
VasEBoot_uint8_t *alpha)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->unmap_color (color,
red,
green,
blue,
alpha);
}
/* Fill rectangle using specified color. */
VasEBoot_err_t
VasEBoot_video_fill_rect (VasEBoot_video_color_t color, int x, int y,
unsigned int width, unsigned int height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->fill_rect (color, x, y, width, height);
}
/* Blit bitmap to screen. */
VasEBoot_err_t
VasEBoot_video_blit_bitmap (struct VasEBoot_video_bitmap *bitmap,
enum VasEBoot_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
unsigned int width, unsigned int height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->blit_bitmap (bitmap, oper, x, y,
offset_x, offset_y,
width, height);
}
/* Blit render target to active render target. */
VasEBoot_err_t
VasEBoot_video_blit_render_target (struct VasEBoot_video_render_target *target,
enum VasEBoot_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
unsigned int width, unsigned int height)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->blit_render_target (target, oper, x, y,
offset_x, offset_y,
width, height);
}
/* Scroll viewport and fill new areas with specified color. */
VasEBoot_err_t
VasEBoot_video_scroll (VasEBoot_video_color_t color, int dx, int dy)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->scroll (color, dx, dy);
}
/* Swap buffers (swap active render target). */
VasEBoot_err_t
VasEBoot_video_swap_buffers (void)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->swap_buffers ();
}
/* Create new render target. */
VasEBoot_err_t
VasEBoot_video_create_render_target (struct VasEBoot_video_render_target **result,
unsigned int width, unsigned int height,
unsigned int mode_type)
{
*result = 0;
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->create_render_target (result,
width, height,
mode_type);
}
/* Delete render target. */
VasEBoot_err_t
VasEBoot_video_delete_render_target (struct VasEBoot_video_render_target *target)
{
if (!target)
return VasEBoot_ERR_NONE;
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->delete_render_target (target);
}
/* Set active render target. */
VasEBoot_err_t
VasEBoot_video_set_active_render_target (struct VasEBoot_video_render_target *target)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->set_active_render_target (target);
}
/* Get active render target. */
VasEBoot_err_t
VasEBoot_video_get_active_render_target (struct VasEBoot_video_render_target **target)
{
if (! VasEBoot_video_adapter_active)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no video mode activated");
return VasEBoot_video_adapter_active->get_active_render_target (target);
}
VasEBoot_err_t
VasEBoot_video_edid_checksum (struct VasEBoot_video_edid_info *edid_info)
{
const char *edid_bytes = (const char *) edid_info;
int i;
char checksum = 0;
/* Check EDID checksum. */
for (i = 0; i < 128; ++i)
checksum += edid_bytes[i];
if (checksum != 0)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE,
"invalid EDID checksum %d", checksum);
VasEBoot_errno = VasEBoot_ERR_NONE;
return VasEBoot_errno;
}
VasEBoot_err_t
VasEBoot_video_edid_preferred_mode (struct VasEBoot_video_edid_info *edid_info,
unsigned int *width, unsigned int *height)
{
/* Bit 1 in the Feature Support field indicates that the first
Detailed Timing Description is the preferred timing mode. */
if (edid_info->version == 1 /* we don't understand later versions */
&& (edid_info->feature_support
& VasEBoot_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE)
&& edid_info->detailed_timings[0].pixel_clock)
{
*width = edid_info->detailed_timings[0].horizontal_active_lo
| (((unsigned int)
(edid_info->detailed_timings[0].horizontal_hi & 0xf0))
<< 4);
*height = edid_info->detailed_timings[0].vertical_active_lo
| (((unsigned int)
(edid_info->detailed_timings[0].vertical_hi & 0xf0))
<< 4);
if (*width && *height)
return VasEBoot_ERR_NONE;
}
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, "no preferred mode available");
}
/* Parse <width>x<height>[x<depth>]*/
static VasEBoot_err_t
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
{
const char *value;
const char *param = current_mode;
*width = *height = *depth = -1;
if (VasEBoot_strcmp (param, "auto") == 0)
{
*width = *height = 0;
return VasEBoot_ERR_NONE;
}
/* Find width value. */
value = param;
param = VasEBoot_strchr(param, 'x');
if (param == NULL)
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("invalid video mode specification `%s'"),
current_mode);
param++;
*width = VasEBoot_strtoul (value, 0, 0);
if (VasEBoot_errno != VasEBoot_ERR_NONE)
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("invalid video mode specification `%s'"),
current_mode);
/* Find height value. */
value = param;
param = VasEBoot_strchr(param, 'x');
if (param == NULL)
{
*height = VasEBoot_strtoul (value, 0, 0);
if (VasEBoot_errno != VasEBoot_ERR_NONE)
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("invalid video mode specification `%s'"),
current_mode);
}
else
{
/* We have optional color depth value. */
param++;
*height = VasEBoot_strtoul (value, 0, 0);
if (VasEBoot_errno != VasEBoot_ERR_NONE)
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("invalid video mode specification `%s'"),
current_mode);
/* Convert color depth value. */
value = param;
*depth = VasEBoot_strtoul (value, 0, 0);
if (VasEBoot_errno != VasEBoot_ERR_NONE)
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("invalid video mode specification `%s'"),
current_mode);
}
return VasEBoot_ERR_NONE;
}
VasEBoot_err_t
VasEBoot_video_set_mode (const char *modestring,
unsigned int modemask,
unsigned int modevalue)
{
char *tmp;
char *next_mode;
char *current_mode;
char *modevar;
if (VasEBoot_video_adapter_active && VasEBoot_video_adapter_active->id == VasEBoot_VIDEO_ADAPTER_CAPTURE)
return VasEBoot_ERR_NONE;
modevalue &= modemask;
/* Take copy of env.var. as we don't want to modify that. */
modevar = VasEBoot_strdup (modestring);
/* Initialize next mode. */
next_mode = modevar;
if (! modevar)
return VasEBoot_errno;
if (VasEBoot_memcmp (next_mode, "keep", sizeof ("keep")) == 0
|| VasEBoot_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
|| VasEBoot_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
{
int suitable = 1;
VasEBoot_err_t err;
if (VasEBoot_video_adapter_active)
{
struct VasEBoot_video_mode_info mode_info;
VasEBoot_memset (&mode_info, 0, sizeof (mode_info));
err = VasEBoot_video_get_info (&mode_info);
if (err)
{
suitable = 0;
VasEBoot_errno = VasEBoot_ERR_NONE;
}
if ((mode_info.mode_type & modemask) != modevalue)
suitable = 0;
}
else if (((VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
&& ((VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
suitable = 0;
if (suitable)
{
VasEBoot_free (modevar);
return VasEBoot_ERR_NONE;
}
next_mode += sizeof ("keep") - 1;
if (! *next_mode)
{
VasEBoot_free (modevar);
/* TRANSLATORS: This doesn't imply that there is no available video
mode at all. All modes may have been filtered out by some criteria.
*/
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("no suitable video mode found"));
}
/* Skip separator. */
next_mode++;
}
/* De-activate last set video adapter. */
if (VasEBoot_video_adapter_active)
{
/* Finalize adapter. */
VasEBoot_video_adapter_active->fini ();
if (VasEBoot_errno != VasEBoot_ERR_NONE)
VasEBoot_errno = VasEBoot_ERR_NONE;
/* Mark active adapter as not set. */
VasEBoot_video_adapter_active = 0;
}
/* Loop until all modes has been tested out. */
while (next_mode != NULL)
{
int width = -1;
int height = -1;
int depth = -1;
VasEBoot_err_t err;
unsigned int flags = modevalue;
unsigned int flagmask = modemask;
/* Use last next_mode as current mode. */
tmp = next_mode;
/* Save position of next mode and separate modes. */
for (; *next_mode; next_mode++)
if (*next_mode == ',' || *next_mode == ';')
break;
if (*next_mode)
{
*next_mode = 0;
next_mode++;
}
else
next_mode = 0;
/* Skip whitespace. */
while (VasEBoot_isspace (*tmp))
tmp++;
/* Initialize token holders. */
current_mode = tmp;
/* XXX: we assume that we're in pure text mode if
no video mode is initialized. Is it always true? */
if (VasEBoot_strcmp (current_mode, "text") == 0)
{
struct VasEBoot_video_mode_info mode_info;
VasEBoot_memset (&mode_info, 0, sizeof (mode_info));
if (((VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0)
|| ((VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0))
{
/* Valid mode found from adapter, and it has been activated.
Specify it as active adapter. */
VasEBoot_video_adapter_active = NULL;
/* Free memory. */
VasEBoot_free (modevar);
return VasEBoot_ERR_NONE;
}
}
err = parse_modespec (current_mode, &width, &height, &depth);
if (err)
{
/* Free memory before returning. */
VasEBoot_free (modevar);
return err;
}
/* Try out video mode. */
/* If user requested specific depth check if this depth is supported. */
if (depth != -1 && (flagmask & VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK)
&&
(((flags & VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK)
!= ((depth << VasEBoot_VIDEO_MODE_TYPE_DEPTH_POS)
& VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK))))
continue;
if (depth != -1)
{
flags |= (depth << VasEBoot_VIDEO_MODE_TYPE_DEPTH_POS)
& VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK;
flagmask |= VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK;
}
/* Try to initialize requested mode. Ignore any errors. */
VasEBoot_video_adapter_t p;
/* Loop thru all possible video adapter trying to find requested mode. */
for (p = VasEBoot_video_adapter_list; p; p = p->next)
{
struct VasEBoot_video_mode_info mode_info;
VasEBoot_memset (&mode_info, 0, sizeof (mode_info));
/* Try to initialize adapter, if it fails, skip to next adapter. */
err = p->init ();
if (err != VasEBoot_ERR_NONE)
{
VasEBoot_errno = VasEBoot_ERR_NONE;
continue;
}
/* Try to initialize video mode. */
err = p->setup (width, height, flags, flagmask);
if (err != VasEBoot_ERR_NONE)
{
p->fini ();
VasEBoot_errno = VasEBoot_ERR_NONE;
continue;
}
err = p->get_info (&mode_info);
if (err != VasEBoot_ERR_NONE)
{
p->fini ();
VasEBoot_errno = VasEBoot_ERR_NONE;
continue;
}
flags = mode_info.mode_type & ~VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK;
flags |= (mode_info.bpp << VasEBoot_VIDEO_MODE_TYPE_DEPTH_POS)
& VasEBoot_VIDEO_MODE_TYPE_DEPTH_MASK;
/* Check that mode is suitable for upper layer. */
if ((flags & VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT)
? (((VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
&& ((VasEBoot_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
: ((flags & modemask) != modevalue))
{
p->fini ();
VasEBoot_errno = VasEBoot_ERR_NONE;
continue;
}
/* Valid mode found from adapter, and it has been activated.
Specify it as active adapter. */
VasEBoot_video_adapter_active = p;
/* Free memory. */
VasEBoot_free (modevar);
return VasEBoot_ERR_NONE;
}
}
/* Free memory. */
VasEBoot_free (modevar);
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT,
N_("no suitable video mode found"));
}