Files

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__*/