487 lines
18 KiB
C++
487 lines
18 KiB
C++
/*
|
|
* Copyright (C) 2021 Amlogic Corporation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef __WAYLAND_DISPLAY_H__
|
|
#define __WAYLAND_DISPLAY_H__
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <poll.h>
|
|
#include <list>
|
|
#include <unordered_map>
|
|
#include <wayland-client-protocol.h>
|
|
#include <wayland-client.h>
|
|
#include "xdg-shell-client-protocol.h"
|
|
#include "fullscreen-shell-unstable-v1-client-protocol.h"
|
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
|
#include "linux-explicit-synchronization-unstable-v1-client-protocol.h"
|
|
#include "viewporter-client-protocol.h"
|
|
#include "weston-direct-display-client-protocol.h"
|
|
#include "aml-config-client-protocol.h"
|
|
#include "wayland-cursor.h"
|
|
#include "Thread.h"
|
|
#include "Poll.h"
|
|
#include "render_plugin.h"
|
|
|
|
using namespace std;
|
|
|
|
#define DEFAULT_DISPLAY_OUTPUT_NUM 2
|
|
|
|
class WaylandPlugin;
|
|
class WaylandShmBuffer;
|
|
class WaylandBuffer;
|
|
|
|
class WaylandDisplay : public ATools::Thread{
|
|
public:
|
|
typedef struct {
|
|
bool enableSetVideoPlane;
|
|
bool enableSetPts;
|
|
bool enableKeepLastFrame;
|
|
bool enableSurfaceDestroyCallback;
|
|
bool enableSetDisplayRate;
|
|
bool enableSetSurfaceInvisible;
|
|
bool enableDisplayTime;
|
|
bool enableForceUpdateRect;
|
|
bool enableVideoOnOSD;
|
|
bool enableNeedOriginalSize;
|
|
bool enableDpss;
|
|
bool enableVsyncCallback;
|
|
} AmlConfigAPIList;
|
|
|
|
WaylandDisplay(WaylandPlugin *plugin, int logCategory);
|
|
virtual ~WaylandDisplay();
|
|
/**
|
|
* @brief connet client to compositor server
|
|
* and acquire a display from compositor
|
|
*
|
|
* @return int 0 success,other fail
|
|
*/
|
|
int openDisplay();
|
|
/**
|
|
* @brief release display that acquired from compositor
|
|
*
|
|
*/
|
|
void closeDisplay();
|
|
/**
|
|
* @brief change RenderVideoFormat to wayland protocol dma buffer format
|
|
* and get the matched dmabuffer modifiers
|
|
*
|
|
*/
|
|
int toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/);
|
|
/**
|
|
* @brief change RenderVideoFormat to wayland protocol shm buffer format
|
|
*
|
|
* @param format RenderVideoFormat
|
|
* @param outformat wayland protocol shm buffer format
|
|
* @return int 0 success,other fail
|
|
*/
|
|
int toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat);
|
|
/**
|
|
* @brief Set the Video Buffer Format object
|
|
*
|
|
* @param format RenderVideoFormat it is defined in render_lib.h
|
|
*/
|
|
void setVideoBufferFormat(RenderVideoFormat format);
|
|
RenderVideoFormat getVideoBufferFormat() {
|
|
return mBufferFormat;
|
|
};
|
|
struct wl_display *getWlDisplay() {
|
|
return mWlDisplay;
|
|
};
|
|
struct weston_direct_display_v1 *getWlDirectDisplay() {
|
|
return mDirect_display;
|
|
};
|
|
struct zwp_linux_dmabuf_v1 * getDmaBuf()
|
|
{
|
|
return mDmabuf;
|
|
};
|
|
struct wl_shm *getShm()
|
|
{
|
|
return mShm;
|
|
};
|
|
|
|
/**
|
|
* @brief Set the Keep Last Frame when playback end
|
|
* #param keep 1:keep last frame, 0:do not keep
|
|
*/
|
|
void setKeepLastFrame(int keep);
|
|
void setKeepLastFrameOnFlush(int keepOnFlush);
|
|
AmlConfigAPIList *getAmlConfigAPIList()
|
|
{
|
|
return &mAmlConfigAPIList;
|
|
};
|
|
/**
|
|
* @brief Set the Select Display Output index
|
|
*
|
|
* @param output selected display output index
|
|
*/
|
|
void setDisplayOutput(int output);
|
|
/**
|
|
* @brief Get the Select Display Output index
|
|
*
|
|
* @return int the index of selected output
|
|
*/
|
|
int getDisplayOutput();
|
|
|
|
int getCurrentOutputCrtcIndex() {
|
|
if (mCurrentDisplayOutput) {
|
|
return mCurrentDisplayOutput->crtcIndex;
|
|
}
|
|
return 0; //default crtc index
|
|
};
|
|
|
|
/**
|
|
* @brief set pip video
|
|
* @param pip if set to 1, the video data will display in pip video plane
|
|
* otherwise video data will display in main video plane
|
|
*/
|
|
void setPip(int pip);
|
|
|
|
void setRedrawingPending(bool val) {
|
|
mRedrawingPending = val;
|
|
};
|
|
|
|
bool isRedrawingPending() {
|
|
return mRedrawingPending;
|
|
};
|
|
|
|
void updateDisplayOutput();
|
|
|
|
void setRenderRectangle(int x, int y, int w, int h);
|
|
void setFrameSize(int w, int h);
|
|
void setWindowSize(int x, int y, int w, int h);
|
|
void setCropSize(int x, int y, int w, int h);
|
|
int prepareFrameBuffer(RenderBuffer * buf);
|
|
void displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime);
|
|
void setOpaque();
|
|
void flushBuffers();
|
|
void ensureFullscreen(bool fullscreen);
|
|
void setPixelAspectRatio(double ratio);
|
|
void pause();
|
|
void resume();
|
|
void underflow();
|
|
void setImmediatelyOutput(int enable);
|
|
int getFrameWidth()
|
|
{
|
|
return mVideoWidth;
|
|
};
|
|
int getFrameHeight()
|
|
{
|
|
return mVideoHeight;
|
|
};
|
|
|
|
void setFrameRate(int frameRateNum, int frameRateDenom);
|
|
|
|
void setVideoPlaneZorder(int zorder);
|
|
int getVideoPlaneZorder() {
|
|
return mVideoPlaneZorder;
|
|
};
|
|
void setRotateVideo(int degree)
|
|
{
|
|
mVideoRotateDegree = degree;
|
|
};
|
|
int getRotateVideo()
|
|
{
|
|
return mVideoRotateDegree;
|
|
};
|
|
int getWaylandBufferCookieId() {
|
|
return mWaylandBufferCookieId;
|
|
};
|
|
int unexpectReleaseFrame(RenderBuffer *buffer);
|
|
void setHideVideo(int hide);
|
|
|
|
struct aml_config* getAmlConfig() {
|
|
return mAmlConfig;
|
|
};
|
|
/*set video displayed on osd*/
|
|
void setVideoOnOSD(int videoOnOSD);
|
|
bool isVideoOnOSD() {
|
|
return mVideoOnOSD;
|
|
};
|
|
void handleBufferReleaseCallback(WaylandBuffer *buf);
|
|
void handleFrameDisplayedCallback(WaylandBuffer *buf);
|
|
void handleFrameDropedCallback(WaylandBuffer *buf);
|
|
/*weston signal frame displayed monotime with this callback*/
|
|
void handleFrameTime(WaylandBuffer *buf,uint32_t sec, uint32_t usec);
|
|
void handleFrameDroppedAndRelease(RenderBuffer * buf);
|
|
int getHWCLatency();
|
|
int getDisplayVsyncAndPeriod(uint64_t *vsyncTimestamp, uint64_t *vsyncPeriod);
|
|
|
|
//thread func
|
|
void readyToRun();
|
|
virtual bool threadLoop();
|
|
void readyToExit();
|
|
int64_t frameCallbackTimeUs; //debug
|
|
/**wayland callback functions**/
|
|
static void dmabuf_modifiers(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
|
|
uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo);
|
|
static void dmaBufferFormat (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format);
|
|
static void registryHandleGlobal (void *data, struct wl_registry *registry,
|
|
uint32_t id, const char *interface, uint32_t version);
|
|
static void registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name);
|
|
static void shmFormat (void *data, struct wl_shm *wl_shm, uint32_t format);
|
|
static void outputHandleGeometry( void *data,
|
|
struct wl_output *output,
|
|
int x,
|
|
int y,
|
|
int mmWidth,
|
|
int mmHeight,
|
|
int subPixel,
|
|
const char *make,
|
|
const char *model,
|
|
int transform );
|
|
static void outputHandleMode( void *data,
|
|
struct wl_output *output,
|
|
uint32_t flags,
|
|
int width,
|
|
int height,
|
|
int refreshRate );
|
|
static void outputHandleDone( void *data,
|
|
struct wl_output *output );
|
|
static void outputHandleScale( void *data,
|
|
struct wl_output *output,
|
|
int32_t scale );
|
|
static void outputHandleCrtcIndex( void *data,
|
|
struct wl_output *output,
|
|
int32_t index );
|
|
static void pointerHandleEnter(void *data, struct wl_pointer *pointer,
|
|
uint32_t serial, struct wl_surface *surface,
|
|
wl_fixed_t sx, wl_fixed_t sy);
|
|
static void pointerHandleLeave(void *data, struct wl_pointer *pointer,
|
|
uint32_t serial, struct wl_surface *surface);
|
|
static void pointerHandleMotion(void *data, struct wl_pointer *pointer,
|
|
uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
|
|
static void pointerHandleButton(void *data, struct wl_pointer *wl_pointer,
|
|
uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
|
|
static void pointerHandleAxis(void *data, struct wl_pointer *wl_pointer,
|
|
uint32_t time, uint32_t axis, wl_fixed_t value);
|
|
static void touchHandleDown(void *data, struct wl_touch *wl_touch,
|
|
uint32_t serial, uint32_t time, struct wl_surface *surface,
|
|
int32_t id, wl_fixed_t x_w, wl_fixed_t y_w);
|
|
static void touchHandleUp(void *data, struct wl_touch *wl_touch,
|
|
uint32_t serial, uint32_t time, int32_t id);
|
|
static void touchHandleMotion(void *data, struct wl_touch *wl_touch,
|
|
uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w);
|
|
static void touchHandleFrame(void *data, struct wl_touch *wl_touch);
|
|
static void touchHandleCancel(void *data, struct wl_touch *wl_touch);
|
|
static void keyboardHandleKeymap(void *data, struct wl_keyboard *keyboard,
|
|
uint32_t format, int fd, uint32_t size);
|
|
static void keyboardHandleEnter(void *data, struct wl_keyboard *keyboard,
|
|
uint32_t serial, struct wl_surface *surface, struct wl_array *keys);
|
|
static void keyboardHandleLeave(void *data, struct wl_keyboard *keyboard,
|
|
uint32_t serial, struct wl_surface *surface);
|
|
static void keyboardHandleKey(void *data, struct wl_keyboard *keyboard,
|
|
uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
|
|
static void keyboardHandleModifiers(void *data, struct wl_keyboard *keyboard,
|
|
uint32_t serial, uint32_t mods_depressed,
|
|
uint32_t mods_latched, uint32_t mods_locked,
|
|
uint32_t group);
|
|
static void seatHandleCapabilities(void *data, struct wl_seat *seat,
|
|
uint32_t caps);
|
|
static void handleXdgToplevelClose (void *data, struct xdg_toplevel *xdg_toplevel);
|
|
static void handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
|
|
int32_t width, int32_t height, struct wl_array *states);
|
|
static void handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface, uint32_t serial);
|
|
static void amlConfigure(void *data, struct aml_config *config, const char *list);
|
|
static void handleSurfaceDestroy(void *data, struct wl_callback *callback, uint32_t time);
|
|
static void surfaceEnter(void *data, struct wl_surface *wl_surface, struct wl_output *output);
|
|
static void surfaceLeave(void *data, struct wl_surface *wl_surface, struct wl_output *output);
|
|
static void surfaceUnderFlow(void *data, struct wl_surface *wl_surface, uint32_t pts_hi, uint32_t pts_lo);
|
|
static void dpssLatency(void *data, struct aml_config *config, uint32_t latency);
|
|
static void vsyncCallback(void *data, struct aml_config *config, uint32_t vsync_hi, uint32_t vsync_lo, uint32_t interval);
|
|
private:
|
|
typedef struct DisplayOutput {
|
|
struct wl_output *wlOutput;
|
|
int offsetX;
|
|
int offsetY;
|
|
int width;
|
|
int height;
|
|
int refreshRate;
|
|
bool isPrimary;
|
|
uint32_t name;
|
|
int32_t crtcIndex;
|
|
} DisplayOutput;
|
|
struct Rectangle {
|
|
int x;
|
|
int y;
|
|
int w;
|
|
int h;
|
|
};
|
|
char *require_xdg_runtime_dir();
|
|
void createCommonWindowSurface();
|
|
void createXdgShellWindowSurface();
|
|
void destroyWindowSurfaces();
|
|
void resizeVideoSurface(bool commit);
|
|
void videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling);
|
|
void updateBorders();
|
|
std::size_t calculateDmaBufferHash(RenderDmaBuffer &dmabuf);
|
|
void cleanSurface();
|
|
void addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf);
|
|
WaylandBuffer* findWaylandBuffer(RenderBuffer * buf);
|
|
void removeWaylandBuffer(RenderBuffer * buf);
|
|
void cleanAllWaylandBuffer();
|
|
void releaseDeferredBuffers();
|
|
int cleanWaylandBufferBeforeResChanged();
|
|
void dumpAllWaylandBuffer();
|
|
void configCropSize(int dma_width, int dma_height);
|
|
bool checkHWRotationAvailable();
|
|
|
|
WaylandPlugin *mWaylandPlugin;
|
|
struct wl_display *mWlDisplay;
|
|
struct wl_display *mWlDisplayWrapper;
|
|
struct wl_event_queue *mWlQueue;
|
|
|
|
struct wl_registry *mRegistry;
|
|
struct wl_compositor *mCompositor;
|
|
struct wl_subcompositor *mSubCompositor;
|
|
struct xdg_wm_base *mXdgWmBase;
|
|
struct wp_viewporter *mViewporter;
|
|
struct zwp_linux_dmabuf_v1 *mDmabuf;
|
|
struct wl_shm *mShm;
|
|
struct wl_seat *mSeat;
|
|
struct wl_pointer *mPointer;
|
|
struct wl_touch *mTouch;
|
|
struct wl_keyboard *mKeyboard;
|
|
struct weston_direct_display_v1 *mDirect_display;
|
|
struct aml_config *mAmlConfig;
|
|
|
|
/*primary output will signal first,so 0 index is primary wl_output, 1 index is extend wl_output*/
|
|
DisplayOutput mOutput[DEFAULT_DISPLAY_OUTPUT_NUM]; //info about wl_output
|
|
/*default is -1, it means user don't select any output,using primary wl_output*/
|
|
int mSelectOutputIndex; // value is -1,0,1, value < DEFAULT_DISPLAY_OUTPUT_NUM
|
|
DisplayOutput *mCurrentDisplayOutput;
|
|
int mLogCategory;
|
|
|
|
std::list<uint32_t> mShmFormats;
|
|
std::unordered_map<uint32_t, uint64_t> mDmaBufferFormats;
|
|
RenderVideoFormat mBufferFormat;
|
|
|
|
mutable ATools::Mutex mBufferMutex;
|
|
mutable ATools::Mutex mMutex;
|
|
ATools::Condition mCondition;
|
|
int mFd;
|
|
ATools::Poll *mPoll;
|
|
|
|
/*the followed is windows variable*/
|
|
mutable ATools::Mutex mRenderMutex;
|
|
struct wl_surface *mAreaSurface;
|
|
struct wl_surface *mAreaSurfaceWrapper;
|
|
struct wl_surface *mVideoSurface;
|
|
struct wl_surface *mVideoSurfaceWrapper;
|
|
struct wl_subsurface *mVideoSubSurface;
|
|
struct xdg_surface *mXdgSurface;
|
|
struct xdg_toplevel *mXdgToplevel;
|
|
struct wp_viewport *mAreaViewport;
|
|
struct wp_viewport *mVideoViewport;
|
|
WaylandShmBuffer *mAreaShmBuffer;
|
|
bool mXdgSurfaceConfigured;
|
|
ATools::Condition mConfigureCond;
|
|
ATools::Mutex mConfigureMutex;
|
|
bool mFullScreen; //default full screen
|
|
|
|
bool mReCommitAreaSurface;
|
|
|
|
bool mUpdateRenderRectangle;
|
|
|
|
/* the size and position of the area_(sub)surface
|
|
it is full screen size now*/
|
|
struct Rectangle mRenderRect;
|
|
|
|
/*the size and position of window */
|
|
struct Rectangle mWindowRect;
|
|
|
|
/*the size of crop window based on origin video frame size*/
|
|
struct Rectangle mCropRect;
|
|
|
|
/* the size and position of the video_subsurface */
|
|
struct Rectangle mVideoRect;
|
|
/* the size of the video in the buffers */
|
|
int mVideoWidth;
|
|
int mVideoHeight;
|
|
|
|
//prepare frame resolution
|
|
int mPrepareFrameWidth;
|
|
int mPrepareFrameHeight;
|
|
int mWaylandBufferCookieId;
|
|
int mUpdateWaylandBuffersMap;
|
|
|
|
//displayed frame resolution
|
|
int mDisplayedFrameWidth;
|
|
int mDisplayedFrameHeight;
|
|
|
|
//the count display buffer of committed to weston
|
|
int mCommitCnt;
|
|
|
|
/*store waylandbuffers when set reusing waylandbuffer flag*/
|
|
std::unordered_map<std::size_t, WaylandBuffer *> mWaylandBuffersMap;
|
|
bool mNoBorderUpdate;
|
|
|
|
/*store committed to weston waylandbuffer,key is pts*/
|
|
std::unordered_map<int64_t, WaylandBuffer *> mCommittedBufferMap;
|
|
|
|
/*buffers deferred for release until after wl_display_disconnect*/
|
|
std::list<RenderBuffer *> mDeferredReleaseBuffers;
|
|
|
|
int mPip; //pip video, 1->pip, 0: main video(default)
|
|
bool mRedrawingPending;//it will be true when weston obtains a buffer rendering,otherwise false when rendered
|
|
AmlConfigAPIList mAmlConfigAPIList;
|
|
int mKeepLastFrame; //keep last frame when playback end
|
|
int mKeepFrameOnFlush;
|
|
bool mMuteVideoOnFlush;
|
|
int64_t mFirstPtsAfterFlush;
|
|
bool mToSendKeepLastFrame; //check if send keep last frame to weston,default false
|
|
bool mSignalFirstFramePts; //signal the first displayed frame pts
|
|
int64_t mFirstFramePts;
|
|
|
|
double mPixelAspectRatio;
|
|
bool mUpdateVideoSurface; //default false
|
|
bool mUpdateCropSize; //default false
|
|
|
|
/*frame rate info*/
|
|
int mFrameRateFractionNum;
|
|
int mFrameRateFractionDenom;
|
|
bool mFrameRateChanged;
|
|
int64_t mPreFramePts;
|
|
int mFrameRateDetectCnt;
|
|
int64_t mFrameRateDetectPeriod;
|
|
int64_t mFrameDurationUs;
|
|
|
|
int mVideoPlaneZorder; //video plane zorder
|
|
bool mVideoPlaneZorderChanged;
|
|
|
|
//freeze frame detected
|
|
int64_t mLastDisplayFramePts; //weston starts displaying frame pts
|
|
int64_t mLastDisplayFrameTimeUs; //weston starts displaying frame system time us
|
|
|
|
// underflow
|
|
bool mVideoIsUnderflow;
|
|
|
|
//video rotate degree
|
|
int mVideoRotateDegree; //default is -1,we often set 0,90,180,270
|
|
bool mEnableWaylandClientLog;
|
|
bool mPaused;
|
|
bool mKeepVideoAsptectRatio;
|
|
bool mHideVideoChanged;//pending hide video set when surface is not ready
|
|
int mHideVideo;
|
|
bool mDisplayConnected; //store state that connected to wayland server
|
|
bool mVideoOnOSD;
|
|
int mDefaultTransform;
|
|
int64_t mVsyncTimeUs;
|
|
int64_t mVsyncPeriodUs;
|
|
|
|
uint32_t mHWCLatency; //dpss latency + drm latency, unit is us
|
|
};
|
|
|
|
#endif /*__WAYLAND_DISPLAY_H__*/ |