XV-Display: the old XVideo display code indeed still works

''it basically works...''
TODO
 - the image is updated only when moving the mouse over the widget
 - calculation of window decoration is not correct
 - a strange transparent zone appears in the UI directly above the widget
This commit is contained in:
Fischlurch 2025-05-08 17:31:27 +02:00
parent 7fd3e71936
commit 5d3710fca8
9 changed files with 83 additions and 66 deletions

View file

@ -18,26 +18,23 @@
** Implementation of a displayer object, intended for creating
** a video display in the UI. This class was created as part of
** an initial draft of the user interface.
** @warning as of 2016 it is not clear, if this code will be
** @todo as of 2016 it is not clear, if this code will be
** evolved into the actual display facility, or be
** replaced and rewritten, when we're about to
** replaced and rewritten, when we're about to
** create a functional video display connected
** to the render engine.
** to the render engine.
** @todo 5/2025 used in an experiment for video output
*/
#include "stage/gtk-base.hpp"
#include "stage/output/displayer.hpp"
#include <cmath>
namespace stage {
namespace output {
bool
Displayer::usable()
{
return false;
}
DisplayerInput
Displayer::format()
{
@ -46,28 +43,26 @@ namespace output {
void
Displayer::calculateVideoLayout(
int widget_width, int widget_height,
int image_width, int image_height,
int &video_x, int &video_y, int &video_width, int &video_height )
int widgetWidth, int widgetHeight,
int &imgOrg_x, int &imgOrg_y, int &imgWidth, int &imgHeight )
{
REQUIRE (widget_width >= 0);
REQUIRE (widget_height >= 0);
REQUIRE (image_width >= 0);
REQUIRE (image_height >= 0);
REQUIRE (0 < widgetWidth );
REQUIRE (0 < widgetHeight);
REQUIRE (0 < videoWidth );
REQUIRE (0 < videoHeight );
double ratio_width = ( double ) widget_width / ( double ) image_width;
double ratio_height = ( double ) widget_height / ( double ) image_height;
double ratio_constant = ratio_height < ratio_width ?
ratio_height : ratio_width;
video_width = ( int ) ( image_width * ratio_constant + 0.5 );
video_height = ( int ) ( image_height * ratio_constant + 0.5 );
video_x = ( widget_width - video_width ) / 2;
video_y = ( widget_height - video_height ) / 2;
auto ratioW = double(widgetWidth ) / videoWidth;
auto ratioH = double(widgetHeight) / videoHeight;
auto scale = std::min (ratioW, ratioH);
imgWidth = std::lround (scale * videoWidth);
imgHeight = std::lround (scale * videoHeight);
imgOrg_x = (widgetWidth - imgWidth) / 2;
imgOrg_y = (widgetHeight - imgHeight) / 2;
ENSURE (video_x >= 0 && video_x < widget_width);
ENSURE (video_y >= 0 && video_y < widget_height);
ENSURE (video_width <= widget_width);
ENSURE (video_width <= widget_width);
ENSURE (imgWidth <= widgetWidth);
ENSURE (imgWidth <= widgetWidth);
ENSURE (0 <= imgOrg_x and imgOrg_x < widgetWidth);
ENSURE (0 <= imgOrg_y and imgOrg_y < widgetHeight);
}

View file

@ -68,20 +68,20 @@ namespace output {
: util::NonCopyable
{
protected:
const int videoWidth;
const int videoHeight;
const uint videoWidth;
const uint videoHeight;
public:
virtual ~Displayer() { }
Displayer(int w, int h)
Displayer(uint w, uint h)
: videoWidth{w}
, videoHeight{h}
{ }
/** Indicates if this object can be used to render images on the running system. */
virtual bool usable();
virtual bool usable() =0;
/** Indicates the format required by the abstract put method.
* @todo this feature was seemingly never used... can it be relevant? can we handle different formats?
@ -99,21 +99,21 @@ namespace output {
/**
* Calculates the coordinates for placing a video image inside a widget
*
* @param[in] widget_width The width of the display widget.
* @param[in] widget_height The height of the display widget.
* @param[in] image_width The width of the video image.
* @param[in] image_height The height of the video image.
* @param[out] video_x The x-coordinate of the top left
* corner of the scaled video image.
* @param[out] video_y The y-coordinate of the top left
* corner of the scaled video image.
* @param[out] video_width The width of the scale video image.
* @param[out] video_height The height of the scale video image.
* @param[in] widgetWidth available width for display in the widget.
* @param[in] widgetHeight available height for display in the widget.
* @param[out] imgOrg_x x-coordinate of the top left corner of the
* scaled video image to display.
* @param[out] imgOrg_y y-coordinate of the top left corner.
* @param[out] imgWidth width of the scale video image to display.
* @param[out] imgHeight height of the scale video image.
*/
static void calculateVideoLayout(
int widget_width, int widget_height,
int image_width, int image_height,
int &video_x, int &video_y, int &video_width, int &video_height );
void calculateVideoLayout(int widgetWidth
,int widgetHeight
,int& imgOrg_x
,int& imgOrg_y
,int& imgWidth
,int& imgHeight
);
};

View file

@ -27,7 +27,7 @@ namespace stage {
namespace output {
NullDisplayer::NullDisplayer (Gtk::Widget& drawing_area,
int width, int height)
uint width, uint height)
: Displayer{width,height}
, drawingArea_{drawing_area}
{
@ -47,7 +47,6 @@ namespace output {
calculateVideoLayout(
drawingArea_.get_width(),
drawingArea_.get_height(),
videoWidth, videoHeight,
video_x, video_y, video_width, video_height);
GdkWindow *window = drawingArea_.get_window()->gobj();

View file

@ -42,7 +42,7 @@ class NullDisplayer
{
public:
NullDisplayer (Gtk::Widget& drawing_area, int width, int height );
NullDisplayer (Gtk::Widget& drawing_area, uint width, uint height );
/** NULL-implementation: accept anything, do nothing */
void put (void* const image) override;

View file

@ -36,7 +36,7 @@ namespace stage {
namespace output {
PixbufDisplayer::PixbufDisplayer (Gtk::Image& drawing_area,
int width, int height)
uint width, uint height)
: Displayer{width,height}
, drawingArea_{drawing_area}
{
@ -56,16 +56,15 @@ namespace output {
void
PixbufDisplayer::put (void* const image)
{
int video_x = 0,
video_y = 0,
int orgX = 0,
orgY = 0,
destWidth = 0,
destHeight = 0;
calculateVideoLayout(
drawingArea_.get_width(),
drawingArea_.get_height(),
videoWidth, videoHeight,
video_x, video_y, destWidth, destHeight);
orgX, orgY, destWidth, destHeight);
GdkWindow *window = drawingArea_.get_window()->gobj();
REQUIRE (window != NULL);
@ -81,7 +80,7 @@ namespace output {
GdkPixbuf *scaled_image = gdk_pixbuf_scale_simple( pixbuf, destWidth, destHeight, GDK_INTERP_NEAREST );
REQUIRE(scaled_image != NULL);
gdk_draw_pixbuf( window, gc, scaled_image, 0, 0, video_x, video_y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 );
gdk_draw_pixbuf( window, gc, scaled_image, 0, 0, orgX, orgY, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 );
g_object_unref( scaled_image );
g_object_unref( pixbuf );

View file

@ -57,7 +57,7 @@ class PixbufDisplayer
* @param[in] height The height of the video image in pixels. This
* value must be greater than zero.
*/
PixbufDisplayer (Gtk::Image& drawing_area, int width, int height );
PixbufDisplayer (Gtk::Image& drawing_area, uint width, uint height );
/**
* Put an image of a given width and height with the expected input

View file

@ -170,6 +170,8 @@ namespace output {
{
gotPort = false;
}
if (not gotPort)
ERROR (stage, "unable to use XVideo for display.");
}
@ -210,18 +212,17 @@ namespace output {
{
REQUIRE(display != NULL);
int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
int org_x = 0, org_y = 0, destW = 0, destH = 0;
calculateVideoLayout(
drawingArea_.get_width(),
drawingArea_.get_height(),
videoWidth, videoHeight,
video_x, video_y, video_width, video_height );
org_x, org_y, destW, destH );
memcpy (xvImage->data, image, xvImage->data_size);
XvShmPutImage (display, grabbedPort, window, gc, xvImage,
0, 0, videoWidth, videoHeight,
video_x, video_y, video_width, video_height, false);
org_x, org_y, destW, destH, false);
}
}

View file

@ -70,11 +70,11 @@ namespace widget {
{
REQUIRE (videoWidth > 0);
REQUIRE (videoHeight > 0);
/*
displayer_ = make_unique<XvDisplayer> (*this, videoWidth, videoHeight);
if (displayer_->usable())
return;
*/
displayer_ = make_unique<PixbufDisplayer> (*this, videoWidth, videoHeight);
if (displayer_->usable())
return;

View file

@ -130027,15 +130027,38 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
Erfolg-1 : es wird <b>irgendwas angezeigt</b>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="full-1"/>
<node CREATED="1746635712253" ID="ID_1901638448" MODIFIED="1746635741949" TEXT="da pa&#xdf;t wohl das Pixel-Layout nicht"/>
<node CREATED="1746635726454" ID="ID_1915597327" MODIFIED="1746635741949" TEXT="aber man sieht den Frame-Takt"/>
<node CREATED="1746635726454" ID="ID_1915597327" MODIFIED="1746710193073" TEXT="man sieht den Frame-Takt"/>
<node CREATED="1746710178642" ID="ID_136906548" MODIFIED="1746710186933" TEXT="aber die Anzeige ist &#xbb;sonderbar&#xab;">
<node CREATED="1746635712253" ID="ID_1901638448" MODIFIED="1746710176681" TEXT="da pa&#xdf;t wohl das Pixel-Layout nicht"/>
<node CREATED="1746710197119" ID="ID_154063098" MODIFIED="1746710231128" TEXT="das Image im Displayer wird vergr&#xf6;&#xdf;ert...">
<node CREATED="1746710231811" ID="ID_1505139667" MODIFIED="1746710240582" TEXT="auf 744 &#xd7; 558 pixels"/>
<node CREATED="1746710241433" ID="ID_581911863" MODIFIED="1746710261314" TEXT="und zwar in dem Moment, wo der PixBuff zum ersten Mal gesetzt wird"/>
<node CREATED="1746710300930" ID="ID_1739522299" MODIFIED="1746710317071" TEXT="trotzdem vestehe ich die Ma&#xdf;e nicht: 320px mal 2 w&#xe4;re 640"/>
<node CREATED="1746710330318" ID="ID_1347613953" MODIFIED="1746710350055" TEXT="das Display-Panel l&#xe4;&#xdf;t sich interaktiv nicht verkleinern (nur vergr&#xf6;&#xdf;ern)"/>
</node>
</node>
<node COLOR="#5b280f" CREATED="1746713519060" ID="ID_1373646714" MODIFIED="1746713539641" TEXT="doch erstmal: den XV-Code untersuchen und (re)aktivieren">
<icon BUILTIN="stop-sign"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746542785647" ID="ID_1968916517" MODIFIED="1746542843774" TEXT="Experiment: den XV-Code aktivieren">
<icon BUILTIN="full-2"/>
<node CREATED="1746718064358" ID="ID_1201089630" MODIFIED="1746718080146" TEXT="erst mal sinngem&#xe4;&#xdf; mit den neuen Widget-Parametern verdrahtet"/>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1746718080949" ID="ID_1374647638" MODIFIED="1746718100295" TEXT="Erfolg-2 : die XV-Anzeige funktioniert grunds&#xe4;tzlich">
<icon BUILTIN="full-2"/>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1746718103627" ID="ID_1187659462" MODIFIED="1746718152643" TEXT="...aber nur, wenn man die Maus &#xfc;ber dem Widget bewegt">
<icon BUILTIN="broken-line"/>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1746718116512" ID="ID_415171245" MODIFIED="1746718148895" TEXT="und die H&#xf6;he der Dekoration ist auch nicht korrekt eingerechnet">
<icon BUILTIN="broken-line"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1746718129879" ID="ID_1760604400" MODIFIED="1746718147158" TEXT="und eine sonderbare durchsichtige Zone ist im GUI">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
</node>
</node>