📄 ppf_watermark.c
字号:
#define ALLOW_OS_CODE 1#include "../../../../emhwlib/include/emhwlib.h"#include "../../../../emhwlib/include/emhwlib_displaytypes.h"#include "../../../../emhwlib/include/emhwlib_properties_1000.h"#include "../../../dock/include/filters.h"#include "../include/ppf_watermark.h"#include <linux/moduleparam.h>#define PPFDBG DISABLE#define GFX_COMMAND_COUNT (32)#define CARBON_MAX_PIC_WIDTH (1920)#define CARBON_MAX_PIC_HEIGHT (1088)#define CARBON_PICTURE_COUNT (7)RMuint32 chip_id;RMuint32 slot_id;RMuint32 tasklet_id;RMuint32 pE;RMuint32 pEm;/* Ignored anyway */#define PGBUS ((struct gbus *)1)/* module_param(slot_id, long, 0); *//* module_param(chip_id, long, 0); *//* TODO * Check that gfx commands could be sent, and retry again later if they didn't.*/#define SEND_GFX_COMMAND(propertyID, pValue, ValueSize) \{ \ if(RMFAILED(EMhwlibSetProperty((struct EMhwlib *)pEm, context.gfx_task, propertyID, pValue, ValueSize))) \ RMDBGLOG((ENABLE, "COULD NOT SEND COMMAND!!\n")); \}/* This filter has only two state: "play" and "stop" */enum ppf_watermark_state{ ppf_watermark_state_play, ppf_watermark_state_stop};struct ppf_watermark_context{ struct EMhwlibSurfaceReader input; RMuint32 carbon_output; RMuint32 marked_output; enum ppf_watermark_state state; RMuint32 on_display_pics; RMuint32 gfx_task; RMuint32 carbon_pictures[CARBON_PICTURE_COUNT]; RMuint32 carbon_pictures_parent[CARBON_PICTURE_COUNT]; RMuint32 carbon_buffers[CARBON_PICTURE_COUNT];};static struct ppf_watermark_context context;RMstatus watermark_get_engine_mem(struct EMhwlibMemoryBlockList *requiredmemblocks);RMstatus watermark_set_engine_mem(struct EMhwlibMemoryBlockList *allocatedmemblocks);RMstatus watermark_get_output_mem(RMuint32 output_slot, struct EMhwlibMemoryBlockList *requiredmemblocks);RMstatus watermark_set_output_mem(RMuint32 output_slot, struct EMhwlibMemoryBlockList *allocatedmemblocks);RMstatus watermark_get_output(RMuint32 output_slot, RMuint32 *output_surface);RMstatus watermark_set_input(RMuint32 input_slot, RMuint32 input_surface);RMstatus watermark_set_command(void *command_param, RMuint32 param_size, void *command_result, RMuint32 result_size);/* these are not part of the handler */RMstatus watermark_run_filter(RMuint32 data);static RMstatus watermark_init(void);static RMstatus watermark_deinit(void);/* Filters functions */RMstatus watermark_get_engine_mem(struct EMhwlibMemoryBlockList *requiredmemblocks){ /* this module does not require any DRAM memory */ RMstatus err; struct GFXEngine_DRAMSize_in_type dramSizeIn; struct GFXEngine_DRAMSize_out_type dramSizeOut; RMDBGLOG((ENABLE, "at watermark set engine mem \n")); dramSizeIn.CommandFIFOCount = GFX_COMMAND_COUNT; err = EMhwlibExchangeProperty((struct EMhwlib *)pEm, EMHWLIB_MODULE(GFXEngine,0), RMGFXEnginePropertyID_DRAMSize, &dramSizeIn, sizeof(dramSizeIn), &dramSizeOut, sizeof(dramSizeOut)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error getting required size for GFX engine\n")); return RM_ERROR; } requiredmemblocks->BlockCount = 1; requiredmemblocks->Blocks[0].Size = dramSizeOut.UncachedSize; return RM_OK;}RMstatus watermark_set_engine_mem(struct EMhwlibMemoryBlockList *allocatedmemblocks){ RMuint32 gfx_count; RMuint32 i; struct GFXEngine_Open_type gfx_profile; RMstatus err; RMDBGLOG((ENABLE, "at watermark set engine mem \n")); if(allocatedmemblocks->BlockCount != 1){ RMDBGLOG((ENABLE, "WARNING: Expecting 1 allocated mem block, got %ld!\n", allocatedmemblocks->BlockCount)); return RM_ERROR; } /* we don't need any memory here */ gfx_profile.CommandFIFOCount = GFX_COMMAND_COUNT; gfx_profile.Priority = 1; gfx_profile.CachedSize = 0; gfx_profile.UncachedSize = allocatedmemblocks->Blocks[0].Size; gfx_profile.UncachedAddress = allocatedmemblocks->Blocks[0].Address; context.gfx_task = GFXEngine; err = EMhwlibExchangeProperty((struct EMhwlib *)pEm, EMHWLIB_MODULE(Enumerator,0), RMEnumeratorPropertyID_CategoryIDToNumberOfInstances, &(context.gfx_task), sizeof(context.gfx_task), &gfx_count, sizeof(gfx_count)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error getting gfx engine count\n")); return RM_ERROR; } for (i=0 ; i<(RMint32) gfx_count ; i++) { context.gfx_task = EMHWLIB_MODULE(GFXEngine, i); err = EMhwlibSetProperty((struct EMhwlib *)pEm, context.gfx_task, RMGFXEnginePropertyID_Open, &gfx_profile, sizeof(gfx_profile)); if (err == RM_OK){ RMDBGLOG((ENABLE, "OK, using task %ld (module id %ld)\n", i, context.gfx_task)); break; } } if (i==(RMint32)gfx_count) { RMDBGLOG((ENABLE, "Could not open a gfx engine task\n")); return -1; } return RM_OK;}RMstatus watermark_get_output_mem(RMuint32 output_slot, struct EMhwlibMemoryBlockList *requiredmemblocks){ RMuint32 surface_size; RMstatus err; RMuint32 picture_count = CARBON_PICTURE_COUNT; /* The pictures are allocated by the creator of the input surfaces (i.e.) no new pictures are needed for the output surfaces. We only need enough memory to create the surface structure. */ if(output_slot != 0){ RMDBGLOG((ENABLE, "Invalid slot!\n")); return RM_ERROR; } err = EMhwlibExchangeProperty((struct EMhwlib *)pEm,DisplayBlock, RMDisplayBlockPropertyID_MultiplePictureSurfaceSize, &picture_count, sizeof(picture_count), &surface_size, sizeof(surface_size)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get the size of a surface\n")); return err; } requiredmemblocks->BlockCount = 3; requiredmemblocks->Blocks[0].Size = surface_size; requiredmemblocks->Blocks[0].Address = 0; requiredmemblocks->Blocks[1].Size = surface_size; requiredmemblocks->Blocks[1].Address = 0; requiredmemblocks->Blocks[2].Size = (CARBON_PICTURE_COUNT*(CARBON_MAX_PIC_WIDTH*CARBON_MAX_PIC_HEIGHT + sizeof(struct EMhwlibNewPicture))); requiredmemblocks->Blocks[2].Address = 0; RMDBGLOG((ENABLE, "sizeof picture is %ld\n", sizeof(struct EMhwlibNewPicture))); return RM_OK;}RMstatus watermark_set_output_mem(RMuint32 output_slot, struct EMhwlibMemoryBlockList *allocatedmemblocks){ struct DisplayBlock_InitMultiplePictureSurfaceX_type surface_init; RMstatus err; RMuint32 i; RMstatus pic_buffer_ptr; if(output_slot != 0){ RMDBGLOG((ENABLE, "Invalid slot!\n")); return RM_ERROR; } if((allocatedmemblocks->BlockCount == 0) ||(allocatedmemblocks->Blocks[0].Address == 0)){ RMDBGLOG((PPFDBG, "Unsetting carbon output slot %ld\n", output_slot)); context.carbon_output = 0; return RM_ERROR; } if(context.carbon_output != 0){ RMDBGLOG((ENABLE, "This slot is used already!\n")); return RM_ERROR; } if(context.marked_output != 0){ RMDBGLOG((ENABLE, "This slot is used already!\n")); return RM_ERROR; } if(allocatedmemblocks->BlockCount != 3){ RMDBGLOG((ENABLE, "Requested 3 blocks, got %ld\n", allocatedmemblocks->BlockCount)); return RM_ERROR; } surface_init.Address = allocatedmemblocks->Blocks[0].Address; surface_init.ColorMode = EMhwlibColorMode_VideoNonInterleaved; surface_init.ColorFormat = EMhwlibColorFormat_24BPP; surface_init.SamplingMode = EMhwlibSamplingMode_420; surface_init.ColorSpace = EMhwlibColorSpace_YUV_601; surface_init.PixelAspectRatio.X = 1; surface_init.PixelAspectRatio.Y = 1; surface_init.PictureCount = CARBON_PICTURE_COUNT; surface_init.STCModuleId = EMHWLIB_MODULE(STC, 0); /* hope */ surface_init.Tiled = 1; err = EMhwlibSetProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_InitMultiplePictureSurfaceX, &surface_init, sizeof(surface_init)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error Cannot initialize surface\n")); return err; } context.carbon_output = surface_init.Address; surface_init.Address = allocatedmemblocks->Blocks[1].Address; surface_init.ColorMode = EMhwlibColorMode_VideoNonInterleaved; surface_init.ColorFormat = EMhwlibColorFormat_24BPP; surface_init.SamplingMode = EMhwlibSamplingMode_420; surface_init.ColorSpace = EMhwlibColorSpace_YUV_601; surface_init.PixelAspectRatio.X = 1; surface_init.PixelAspectRatio.Y = 1; surface_init.PictureCount = CARBON_PICTURE_COUNT; surface_init.STCModuleId = EMHWLIB_MODULE(STC, 0); /* hope */ surface_init.Tiled = 1; err = EMhwlibSetProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_InitMultiplePictureSurfaceX, &surface_init, sizeof(surface_init)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error Cannot initialize surface\n")); return err; } context.marked_output = surface_init.Address; pic_buffer_ptr = allocatedmemblocks->Blocks[2].Address; for(i = 0; i < CARBON_PICTURE_COUNT; i++){ /* TODO: Check that size is correct */ context.carbon_pictures[i] = pic_buffer_ptr; pic_buffer_ptr += sizeof(struct EMhwlibNewPicture); } pic_buffer_ptr = (pic_buffer_ptr + 4095) & (~4095); /* align to 4k */ for(i = 0; i < CARBON_PICTURE_COUNT; i++){ context.carbon_buffers[i] = pic_buffer_ptr; pic_buffer_ptr += CARBON_MAX_PIC_WIDTH*CARBON_MAX_PIC_HEIGHT; } for(i = 0; i < CARBON_PICTURE_COUNT; i++){ struct EMhwlibNewPicture *carbon_pic; carbon_pic = (struct EMhwlibNewPicture*)context.carbon_pictures[i]; gbus_write_uint32(PGBUS, (RMuint32) & (carbon_pic->picture_display_status), 0); RMDBGLOG((ENABLE, "final: 0x%08lx:0x%08lx\n", context.carbon_pictures[i], context.carbon_buffers[i])); } RMDBGLOG((ENABLE, "Initialized output surface at 0x%08lx\n", context.carbon_output)); return RM_OK;}RMstatus watermark_get_output(RMuint32 output_slot, RMuint32 *output_surface){ if(output_slot != 0){ RMDBGLOG((ENABLE, "Invalid slot!\n")); return RM_ERROR; } *output_surface = context.marked_output; return RM_OK;}RMstatus watermark_set_input(RMuint32 input_slot, RMuint32 input_surface){ RMuint32 reader_id; RMstatus err = RM_OK; /* This filter only support one input slot */ if(input_slot!=0){ RMDBGLOG((ENABLE, "Invalid slot\n")); return RM_ERROR; } if(input_surface == 0){ RMDBGLOG((ENABLE, "Unseting input surface slot\n")); context.input.SurfaceAddress = 0; return RM_OK; } if(context.input.SurfaceAddress != 0){ RMDBGLOG((ENABLE, "Input Surface already used!\n")); return RM_ERROR; } context.input.SurfaceAddress = input_surface; /* TODO: We should check that the input surface is * compatible with the output surface */ /* The ConnectReader API says that we can put the "desired" reader id here but it may change during the call */ context.input.ReaderID = 0; /* 0 = input slot - Only one in this case */ err = EMhwlibExchangeProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_ConnectReader, &context.input, sizeof(context.input), &reader_id, sizeof(reader_id)); if(RMFAILED(err)){ RMDBGLOG((ENABLE, "Connect reader failed: unsetting input\n")); context.input.SurfaceAddress = 0; return RM_ERROR; } /* This is the one to use */ context.input.ReaderID = reader_id; RMDBGLOG((PPFDBG,"connected to surface 0x%08lx with reader_id %ld\n", input_surface, reader_id)); /* Surface properties : */ { /* HACK: there is no property, so we do this ugly typecasting to look at * the real structure behind the opaque address */ struct EMhwlibSurface *s; s = (struct EMhwlibSurface *)input_surface; RMDBGLOG((ENABLE, "Surface: module id=%08x, video_timer=%08x, tiled=%08x\n", gbus_read_uint32(PGBUS, (RMuint32)&s->module_id), gbus_read_uint32(PGBUS, (RMuint32)&s->video_timer_index), gbus_read_uint32(PGBUS, (RMuint32)&s->tiled) )); } return RM_OK;}RMstatus watermark_set_command(void *command_param, RMuint32 param_size, void *command_result, RMuint32 result_size){ enum ppf_watermark_cmd cmd; RMDBGLOG((ENABLE, "at command param\n")); if(param_size != sizeof(enum ppf_watermark_cmd)){ RMDBGLOG((ENABLE, "Invalid param size!\n")); return RM_ERROR; } if(command_param == NULL){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -