mesa: Changes to 'upstream-experimental'
Rebased ref, commits from common ancestor:
commit 68bba1801eb49f749ea91e36905d3b99245fa03c
Author: Christian König <christian.koenig@amd.com>
Date: Sun Apr 6 17:07:41 2014 +0200
st/omx/enc: separate input buffer private and task structure
Keep tasks as linked list, this way we can associate
more than one encoding task with each buffer.
Signed-off-by: Christian König <christian.koenig@amd.com>
diff --git a/src/gallium/state_trackers/omx/vid_enc.c b/src/gallium/state_trackers/omx/vid_enc.c
index 080730b..88d15a9 100644
--- a/src/gallium/state_trackers/omx/vid_enc.c
+++ b/src/gallium/state_trackers/omx/vid_enc.c
@@ -54,12 +54,18 @@
#include "entrypoint.h"
#include "vid_enc.h"
-struct input_buf_private {
+struct encode_task {
+ struct list_head list;
+
struct pipe_video_buffer *buf;
struct pipe_resource *bitstream;
void *feedback;
};
+struct input_buf_private {
+ struct list_head tasks;
+};
+
struct output_buf_private {
struct pipe_resource *bitstream;
struct pipe_transfer *transfer;
@@ -79,6 +85,8 @@ static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOU
static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf);
static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output);
+static void enc_ReleaseTasks(struct list_head *head);
+
static void vid_enc_name(char str[OMX_MAX_STRINGNAME_SIZE])
{
snprintf(str, OMX_MAX_STRINGNAME_SIZE, OMX_VID_ENC_BASE_NAME, driver_descriptor.name);
@@ -243,6 +251,9 @@ static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING nam
priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT;
priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT;
+ LIST_INITHEAD(&priv->free_tasks);
+ LIST_INITHEAD(&priv->used_tasks);
+
return OMX_ErrorNone;
}
@@ -251,6 +262,9 @@ static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp)
vid_enc_PrivateType* priv = comp->pComponentPrivate;
int i;
+ enc_ReleaseTasks(&priv->free_tasks);
+ enc_ReleaseTasks(&priv->used_tasks);
+
if (priv->ports) {
for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) {
if(priv->ports[i])
@@ -563,9 +577,10 @@ static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalReq
static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf)
{
struct input_buf_private *inp = buf->pInputPortPrivate;
- pipe_resource_reference(&inp->bitstream, NULL);
- inp->buf->destroy(inp->buf);
- FREE(inp);
+ if (inp) {
+ enc_ReleaseTasks(&inp->tasks);
+ FREE(inp);
+ }
return base_port_FreeBuffer(port, idx, buf);
}
@@ -607,22 +622,25 @@ static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx,
return base_port_FreeBuffer(port, idx, buf);
}
-static OMX_ERRORTYPE enc_NeedInputPortPrivate(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)
+static struct encode_task *enc_NeedTask(omx_base_PortType *port)
{
+ OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
OMX_COMPONENTTYPE* comp = port->standCompContainer;
vid_enc_PrivateType *priv = comp->pComponentPrivate;
- OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
- struct input_buf_private **inp = (struct input_buf_private **)&buf->pInputPortPrivate;
+
struct pipe_video_buffer templat = {};
+ struct encode_task *task;
- if (*inp) {
- pipe_resource_reference(&(*inp)->bitstream, NULL);
- return OMX_ErrorNone;
+ if (!LIST_IS_EMPTY(&priv->free_tasks)) {
+ task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list);
+ LIST_DEL(&task->list);
+ return task;
}
- if (!(*inp = CALLOC(1, sizeof(struct input_buf_private)))) {
- return OMX_ErrorInsufficientResources;
- }
+ /* allocate a new one */
+ task = CALLOC_STRUCT(encode_task);
+ if (!task)
+ return NULL;
templat.buffer_format = PIPE_FORMAT_NV12;
templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
@@ -630,25 +648,46 @@ static OMX_ERRORTYPE enc_NeedInputPortPrivate(omx_base_PortType *port, OMX_BUFFE
templat.height = def->nFrameHeight;
templat.interlaced = false;
- if (!((*inp)->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat))) {
- FREE(*inp);
- return OMX_ErrorInsufficientResources;
+ task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat);
+ if (!task->buf) {
+ FREE(task);
+ return NULL;
}
- return OMX_ErrorNone;
+ return task;
+}
+
+static void enc_MoveTasks(struct list_head *from, struct list_head *to)
+{
+ to->prev->next = from->next;
+ from->next->prev = to->prev;
+ from->prev->next = to;
+ to->prev = from->prev;
+ LIST_INITHEAD(from);
}
-static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)
+static void enc_ReleaseTasks(struct list_head *head)
+{
+ struct encode_task *i, *next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) {
+ pipe_resource_reference(&i->bitstream, NULL);
+ i->buf->destroy(i->buf);
+ FREE(i);
+ }
+}
+
+static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf,
+ struct pipe_video_buffer *vbuf)
{
OMX_COMPONENTTYPE* comp = port->standCompContainer;
vid_enc_PrivateType *priv = comp->pComponentPrivate;
OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
- struct input_buf_private *inp = buf->pInputPortPrivate;
struct pipe_sampler_view **views;
struct pipe_box box = {};
void *ptr;
- views = inp->buf->get_sampler_view_planes(inp->buf);
+ views = vbuf->get_sampler_view_planes(vbuf);
if (!views)
return OMX_ErrorInsufficientResources;
@@ -669,14 +708,12 @@ static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE
return OMX_ErrorNone;
}
-static void enc_ScaleInput(omx_base_PortType *port,
- OMX_BUFFERHEADERTYPE *buf, struct pipe_video_buffer **vbuf, unsigned *size)
+static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size)
{
OMX_COMPONENTTYPE* comp = port->standCompContainer;
vid_enc_PrivateType *priv = comp->pComponentPrivate;
OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
- struct pipe_video_buffer *src_buf =
- ((struct input_buf_private *)buf->pInputPortPrivate)->buf;
+ struct pipe_video_buffer *src_buf = *vbuf;
struct vl_compositor *compositor = &priv->compositor;
struct vl_compositor_state *s = &priv->cstate;
struct pipe_sampler_view **views;
@@ -711,8 +748,7 @@ static void enc_ScaleInput(omx_base_PortType *port,
priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS;
}
-static void enc_ControlPicture(omx_base_PortType *port,
- struct pipe_h264_enc_picture_desc *picture)
+static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture)
{
OMX_COMPONENTTYPE* comp = port->standCompContainer;
vid_enc_PrivateType *priv = comp->pComponentPrivate;
@@ -783,19 +819,48 @@ static void enc_ControlPicture(omx_base_PortType *port,
priv->force_pic_type.IntraRefreshVOP = OMX_FALSE;
}
-static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)
+static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task)
{
OMX_COMPONENTTYPE* comp = port->standCompContainer;
vid_enc_PrivateType *priv = comp->pComponentPrivate;
unsigned size = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize;
- struct pipe_h264_enc_picture_desc picture;
- struct input_buf_private *inp;
- struct pipe_video_buffer *vbuf;
+ struct pipe_video_buffer *vbuf = task->buf;
+ struct pipe_h264_enc_picture_desc picture = {};
+
+ /* -------------- scale input image --------- */
+ enc_ScaleInput(port, &vbuf, &size);
+ priv->s_pipe->flush(priv->s_pipe, NULL, 0);
+
+ /* -------------- allocate output buffer --------- */
+ task->bitstream = pipe_buffer_create(priv->s_pipe->screen, PIPE_BIND_VERTEX_BUFFER,
+ PIPE_USAGE_STREAM, size);
+ enc_ControlPicture(port, &picture);
+
+ /* -------------- encode frame --------- */
+ priv->codec->begin_frame(priv->codec, vbuf, &picture.base);
+ priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback);
+ priv->codec->end_frame(priv->codec, vbuf, &picture.base);
+}
+
+static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)
+{
+ OMX_COMPONENTTYPE* comp = port->standCompContainer;
+ vid_enc_PrivateType *priv = comp->pComponentPrivate;
+ struct input_buf_private *inp = buf->pInputPortPrivate;
+ struct encode_task *task;
OMX_ERRORTYPE err;
- err = enc_NeedInputPortPrivate(port, buf);
- if (err != OMX_ErrorNone)
- return err;
+ if (!inp) {
+ inp = buf->pInputPortPrivate = CALLOC_STRUCT(input_buf_private);
+ if (!inp)
+ return OMX_ErrorInsufficientResources;
+ LIST_INITHEAD(&inp->tasks);
+ } else
+ enc_MoveTasks(&inp->tasks, &priv->free_tasks);
+
+ task = enc_NeedTask(port);
+ if (!task)
+ return OMX_ErrorInsufficientResources;
if (buf->nFilledLen == 0) {
if (buf->nFlags & OMX_BUFFERFLAG_EOS)
@@ -803,47 +868,45 @@ static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEAD
return base_port_SendBufferFunction(port, buf);
}
- inp = buf->pInputPortPrivate;
if (buf->pOutputPortPrivate) {
- vbuf = buf->pOutputPortPrivate;
- buf->pOutputPortPrivate = inp->buf;
- inp->buf = vbuf;
+ struct pipe_video_buffer *vbuf = buf->pOutputPortPrivate;
+ buf->pOutputPortPrivate = task->buf;
+ task->buf = vbuf;
} else {
/* ------- load input image into video buffer ---- */
- err = enc_LoadImage(port, buf);
+ err = enc_LoadImage(port, buf, task->buf);
if (err != OMX_ErrorNone)
return err;
}
- vbuf = inp->buf;
-
- /* -------------- scale input image --------- */
- enc_ScaleInput(port, buf, &vbuf, &size);
- priv->s_pipe->flush(priv->s_pipe, NULL, 0);
- /* -------------- allocate output buffer --------- */
- inp->bitstream = pipe_buffer_create(priv->s_pipe->screen, PIPE_BIND_VERTEX_BUFFER,
- PIPE_USAGE_STREAM, size);
- enc_ControlPicture(port, &picture);
+ enc_HandleTask(port, task);
- /* -------------- encode frame --------- */
- priv->codec->begin_frame(priv->codec, vbuf, &picture.base);
- priv->codec->encode_bitstream(priv->codec, vbuf, inp->bitstream, &inp->feedback);
- priv->codec->end_frame(priv->codec, vbuf, &picture.base);
+ /* put list of encode operations on input buffer */
+ LIST_ADDTAIL(&task->list, &inp->tasks);
return base_port_SendBufferFunction(port, buf);
}
static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output)
{
- struct input_buf_private *inp = input->pInputPortPrivate;
vid_enc_PrivateType *priv = comp->pComponentPrivate;
struct output_buf_private *outp = output->pOutputPortPrivate;
+ struct input_buf_private *inp = input->pInputPortPrivate;
+ struct encode_task *task;
struct pipe_box box = {};
unsigned size;
- input->nFilledLen = 0; /* mark buffer as empty */
+ if (!inp || LIST_IS_EMPTY(&inp->tasks)) {
+ input->nFilledLen = 0; /* mark buffer as empty */
+ enc_MoveTasks(&priv->used_tasks, &inp->tasks);
+ return;
+ }
+
+ task = LIST_ENTRY(struct encode_task, inp->tasks.next, list);
+ LIST_DEL(&task->list);
+ LIST_ADDTAIL(&task->list, &priv->used_tasks);
- if (!inp->bitstream)
+ if (!task->bitstream)
return;
/* ------------- map result buffer ----------------- */
@@ -851,11 +914,12 @@ static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE*
if (outp->transfer)
pipe_transfer_unmap(priv->t_pipe, outp->transfer);
- pipe_resource_reference(&outp->bitstream, inp->bitstream);
+ pipe_resource_reference(&outp->bitstream, task->bitstream);
+ pipe_resource_reference(&task->bitstream, NULL);
- box.width = inp->bitstream->width0;
- box.height = inp->bitstream->height0;
- box.depth = inp->bitstream->depth0;
+ box.width = outp->bitstream->width0;
+ box.height = outp->bitstream->height0;
+ box.depth = outp->bitstream->depth0;
output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0,
PIPE_TRANSFER_READ_WRITE,
@@ -863,7 +927,7 @@ static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE*
/* ------------- get size of result ----------------- */
- priv->codec->get_feedback(priv->codec, inp->feedback, &size);
+ priv->codec->get_feedback(priv->codec, task->feedback, &size);
output->nOffset = 0;
output->nFilledLen = size; /* mark buffer as full */
diff --git a/src/gallium/state_trackers/omx/vid_enc.h b/src/gallium/state_trackers/omx/vid_enc.h
index a3fdfae..76bfbea 100644
--- a/src/gallium/state_trackers/omx/vid_enc.h
+++ b/src/gallium/state_trackers/omx/vid_enc.h
@@ -41,6 +41,8 @@
#include <bellagio/st_static_component_loader.h>
#include <bellagio/omx_base_filter.h>
+#include "util/u_double_list.h"
+
#include "vl/vl_defines.h"
#include "vl/vl_compositor.h"
@@ -67,6 +69,8 @@ DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType)
struct pipe_context *s_pipe; \
struct pipe_context *t_pipe; \
struct pipe_video_codec *codec; \
+ struct list_head free_tasks; \
+ struct list_head used_tasks; \
OMX_U32 frame_rate; \
OMX_U32 frame_num; \
OMX_VIDEO_PARAM_BITRATETYPE bitrate; \
commit 7806dbeb706ac6beb50c29f3c1041700feb9daf0
Author: Christian König <christian.koenig@amd.com>
Date: Fri Apr 4 17:14:26 2014 +0200
radeon/vce: implement B-frame support
Signed-off-by: Slava Grigorev <slava.grigorev@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
diff --git a/src/gallium/drivers/radeon/radeon_vce.h b/src/gallium/drivers/radeon/radeon_vce.h
index f815cad..7cc87be 100644
--- a/src/gallium/drivers/radeon/radeon_vce.h
+++ b/src/gallium/drivers/radeon/radeon_vce.h
@@ -45,7 +45,7 @@
#define RVCE_READWRITE(buf, domain) RVCE_CS(RVCE_RELOC(buf, RADEON_USAGE_READWRITE, domain) * 4)
#define RVCE_END() *begin = (&enc->cs->buf[enc->cs->cdw] - begin) * 4; }
-#define RVCE_NUM_CPB_FRAMES 2
+#define RVCE_NUM_CPB_FRAMES 3
struct r600_common_screen;
diff --git a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
index 1327d64..3b67b31 100644
--- a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
+++ b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
@@ -54,6 +54,11 @@ static struct rvce_cpb_slot *l0_slot(struct rvce_encoder *enc)
return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.next, list);
}
+static struct rvce_cpb_slot *l1_slot(struct rvce_encoder *enc)
+{
+ return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.next->next, list);
+}
+
static void frame_offset(struct rvce_encoder *enc, struct rvce_cpb_slot *slot,
unsigned *luma_offset, unsigned *chroma_offset)
{
@@ -99,8 +104,8 @@ static void create(struct rvce_encoder *enc)
RVCE_BEGIN(0x01000001); // create cmd
RVCE_CS(0x00000000); // encUseCircularBuffer
- RVCE_CS(0x00000041); // encProfile
- RVCE_CS(0x0000000a); // encLevel
+ RVCE_CS(0x0000004d); // encProfile: Main
+ RVCE_CS(0x0000002a); // encLevel: 4.2
RVCE_CS(0x00000000); // encPicStructRestriction
RVCE_CS(enc->base.width); // encImageWidth
RVCE_CS(enc->base.height); // encImageHeight
@@ -175,12 +180,12 @@ static void pic_control(struct rvce_encoder *enc)
RVCE_CS(0x00000000); // encSPSID
RVCE_CS(0x00000000); // encPPSID
RVCE_CS(0x00000040); // encConstraintSetFlags
- RVCE_CS(0x00000000); // encBPicPattern
+ RVCE_CS(MAX2(enc->base.max_references, 1) - 1); // encBPicPattern
RVCE_CS(0x00000000); // weightPredModeBPicture
RVCE_CS(MIN2(enc->base.max_references, 2)); // encNumberOfReferenceFrames
RVCE_CS(enc->base.max_references + 1); // encMaxNumRefFrames
- RVCE_CS(0x00000000); // encNumDefaultActiveRefL0
- RVCE_CS(0x00000000); // encNumDefaultActiveRefL1
+ RVCE_CS(0x00000001); // encNumDefaultActiveRefL0
+ RVCE_CS(0x00000001); // encNumDefaultActiveRefL1
RVCE_CS(0x00000000); // encSliceMode
RVCE_CS(0x00000000); // encMaxSliceSize
RVCE_END();
@@ -275,7 +280,7 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0x00000000); // encInputPic(Addr|Array)Mode
RVCE_CS(0x00000000); // encInputPicTileConfig
RVCE_CS(enc->pic.picture_type); // encPicType
- RVCE_CS(enc->pic.picture_type == 3); // encIdrFlag
+ RVCE_CS(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR); // encIdrFlag
RVCE_CS(0x00000000); // encIdrPicId
RVCE_CS(0x00000000); // encMGSKeyPic
RVCE_CS(0x00000001); // encReferenceFlag
@@ -283,7 +288,17 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0x00000000); // num_ref_idx_active_override_flag
RVCE_CS(0x00000000); // num_ref_idx_l0_active_minus1
RVCE_CS(0x00000000); // num_ref_idx_l1_active_minus1
- for (i = 0; i < 4; ++i) {
+
+ i = enc->pic.frame_num - enc->pic.ref_idx_l0;
+ if (i > 1 && enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P) {
+ RVCE_CS(0x00000001); // encRefListModificationOp
+ RVCE_CS(i - 1); // encRefListModificationNum
+ } else {
+ RVCE_CS(0x00000000); // encRefListModificationOp
+ RVCE_CS(0x00000000); // encRefListModificationNum
+ }
+
+ for (i = 0; i < 3; ++i) {
RVCE_CS(0x00000000); // encRefListModificationOp
RVCE_CS(0x00000000); // encRefListModificationNum
}
@@ -291,22 +306,14 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0x00000000); // encDecodedPictureMarkingOp
RVCE_CS(0x00000000); // encDecodedPictureMarkingNum
RVCE_CS(0x00000000); // encDecodedPictureMarkingIdx
- }
- for (i = 0; i < 4; ++i) {
RVCE_CS(0x00000000); // encDecodedRefBasePictureMarkingOp
RVCE_CS(0x00000000); // encDecodedRefBasePictureMarkingNum
}
+ // encReferencePictureL0[0]
RVCE_CS(0x00000000); // pictureStructure
-
- if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR) {
- RVCE_CS(0x00000000); // encPicType
- RVCE_CS(0x00000000); // frameNumber
- RVCE_CS(0x00000000); // pictureOrderCount
- RVCE_CS(0xffffffff); // lumaOffset
- RVCE_CS(0xffffffff); // chromaOffset
- }
- else if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P) {
+ if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P ||
+ enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) {
struct rvce_cpb_slot *l0 = l0_slot(enc);
frame_offset(enc, l0, &luma_offset, &chroma_offset);
RVCE_CS(l0->picture_type); // encPicType
@@ -314,16 +321,40 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(l0->pic_order_cnt); // pictureOrderCount
RVCE_CS(luma_offset); // lumaOffset
RVCE_CS(chroma_offset); // chromaOffset
+ } else {
+ RVCE_CS(0x00000000); // encPicType
+ RVCE_CS(0x00000000); // frameNumber
+ RVCE_CS(0x00000000); // pictureOrderCount
+ RVCE_CS(0xffffffff); // lumaOffset
+ RVCE_CS(0xffffffff); // chromaOffset
}
- for (i = 0; i < 2; ++i) {
- RVCE_CS(0x00000000); // pictureStructure
+
+ // encReferencePictureL0[1]
+ RVCE_CS(0x00000000); // pictureStructure
+ RVCE_CS(0x00000000); // encPicType
+ RVCE_CS(0x00000000); // frameNumber
+ RVCE_CS(0x00000000); // pictureOrderCount
+ RVCE_CS(0xffffffff); // lumaOffset
+ RVCE_CS(0xffffffff); // chromaOffset
+
+ // encReferencePictureL1[0]
+ RVCE_CS(0x00000000); // pictureStructure
+ if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) {
+ struct rvce_cpb_slot *l1 = l1_slot(enc);
+ frame_offset(enc, l1, &luma_offset, &chroma_offset);
+ RVCE_CS(l1->picture_type); // encPicType
+ RVCE_CS(l1->frame_num); // frameNumber
+ RVCE_CS(l1->pic_order_cnt); // pictureOrderCount
+ RVCE_CS(luma_offset); // lumaOffset
+ RVCE_CS(chroma_offset); // chromaOffset
+ } else {
RVCE_CS(0x00000000); // encPicType
RVCE_CS(0x00000000); // frameNumber
RVCE_CS(0x00000000); // pictureOrderCount
RVCE_CS(0xffffffff); // lumaOffset
RVCE_CS(0xffffffff); // chromaOffset
}
-
+
frame_offset(enc, current_slot(enc), &luma_offset, &chroma_offset);
RVCE_CS(luma_offset); // encReconstructedLumaOffset
RVCE_CS(chroma_offset); // encReconstructedChromaOffset
commit a56fa0e83b7ba7d2d34179e782abe795a399a001
Author: Christian König <christian.koenig@amd.com>
Date: Fri Apr 4 15:29:18 2014 +0200
radeon/vce: add proper CPB backtrack
Remember what frames we encoded at which position.
Signed-off-by: Christian König <christian.koenig@amd.com>
diff --git a/src/gallium/drivers/radeon/radeon_vce.c b/src/gallium/drivers/radeon/radeon_vce.c
index 012b4f8..a7dfcda 100644
--- a/src/gallium/drivers/radeon/radeon_vce.c
+++ b/src/gallium/drivers/radeon/radeon_vce.c
@@ -80,6 +80,57 @@ static void dump_feedback(struct rvce_encoder *enc, struct rvid_buffer *fb)
#endif
/**
+ * reset the CPB handling
+ */
+static void reset_cpb(struct rvce_encoder *enc)
+{
+ unsigned i;
+
+ LIST_INITHEAD(&enc->cpb_slots);
+ for (i = 0; i < RVCE_NUM_CPB_FRAMES; ++i) {
+ struct rvce_cpb_slot *slot = &enc->cpb_array[i];
+ slot->index = i;
+ slot->picture_type = PIPE_H264_ENC_PICTURE_TYPE_SKIP;
+ slot->frame_num = 0;
+ slot->pic_order_cnt = 0;
+ LIST_ADDTAIL(&slot->list, &enc->cpb_slots);
+ }
+}
+
+/**
+ * sort l0 and l1 to the top of the list
+ */
+static void sort_cpb(struct rvce_encoder *enc)
+{
+ struct rvce_cpb_slot *i, *l0 = NULL, *l1 = NULL;
+
+ LIST_FOR_EACH_ENTRY(i, &enc->cpb_slots, list) {
+ if (i->frame_num == enc->pic.ref_idx_l0)
+ l0 = i;
+
+ if (i->frame_num == enc->pic.ref_idx_l1)
+ l1 = i;
+
+ if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P && l0)
+ break;
+
+ if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_B &&
+ l0 && l1)
+ break;
+ }
+
+ if (l1) {
+ LIST_DEL(&l1->list);
+ LIST_ADD(&l1->list, &enc->cpb_slots);
+ }
+
+ if (l0) {
+ LIST_DEL(&l0->list);
+ LIST_ADD(&l0->list, &enc->cpb_slots);
+ }
+}
+
+/**
* destroy this video encoder
*/
static void rvce_destroy(struct pipe_video_codec *encoder)
@@ -97,6 +148,7 @@ static void rvce_destroy(struct pipe_video_codec *encoder)
}
rvid_destroy_buffer(&enc->cpb);
enc->ws->cs_destroy(enc->cs);
+ FREE(enc->cpb_array);
FREE(enc);
}
@@ -118,6 +170,12 @@ static void rvce_begin_frame(struct pipe_video_codec *encoder,
enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma);
enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma);
+
+ if (pic->picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR)
+ reset_cpb(enc);
+ else if (pic->picture_type == PIPE_H264_ENC_PICTURE_TYPE_P ||
+ pic->picture_type == PIPE_H264_ENC_PICTURE_TYPE_B)
+ sort_cpb(enc);
if (!enc->stream_handle) {
struct rvid_buffer fb;
@@ -167,7 +225,17 @@ static void rvce_end_frame(struct pipe_video_codec *encoder,
struct pipe_picture_desc *picture)
{
struct rvce_encoder *enc = (struct rvce_encoder*)encoder;
+ struct rvce_cpb_slot *slot = LIST_ENTRY(
+ struct rvce_cpb_slot, enc->cpb_slots.prev, list);
+
flush(enc);
+
+ /* update the CPB backtrack with the just encoded frame */
+ LIST_DEL(&slot->list);
+ slot->picture_type = enc->pic.picture_type;
+ slot->frame_num = enc->pic.frame_num;
+ slot->pic_order_cnt = enc->pic.pic_order_cnt;
+ LIST_ADD(&slot->list, &enc->cpb_slots);
}
static void rvce_get_feedback(struct pipe_video_codec *encoder,
@@ -213,7 +281,7 @@ struct pipe_video_codec *rvce_create_encoder(struct pipe_context *context,
struct rvce_encoder *enc;
struct pipe_video_buffer *tmp_buf, templat = {};
struct radeon_surface *tmp_surf;
- unsigned pitch, vpitch;
+ unsigned cpb_size;
if (!rscreen->info.vce_fw_version) {
RVID_ERR("Kernel doesn't supports VCE!\n");
@@ -258,16 +326,22 @@ struct pipe_video_codec *rvce_create_encoder(struct pipe_context *context,
}
get_buffer(((struct vl_video_buffer *)tmp_buf)->resources[0], NULL, &tmp_surf);
- pitch = align(tmp_surf->level[0].pitch_bytes, 128);
- vpitch = align(tmp_surf->npix_y, 16);
+ cpb_size = align(tmp_surf->level[0].pitch_bytes, 128);
+ cpb_size = cpb_size * align(tmp_surf->npix_y, 16);
+ cpb_size = cpb_size * 3 / 2;
+ cpb_size = cpb_size * RVCE_NUM_CPB_FRAMES;
tmp_buf->destroy(tmp_buf);
- if (!rvid_create_buffer(enc->ws, &enc->cpb,
- pitch * vpitch * 1.5 * RVCE_NUM_CPB_FRAMES,
- RADEON_DOMAIN_VRAM)) {
+ if (!rvid_create_buffer(enc->ws, &enc->cpb, cpb_size, RADEON_DOMAIN_VRAM)) {
RVID_ERR("Can't create CPB buffer.\n");
goto error;
}
+ enc->cpb_array = CALLOC(RVCE_NUM_CPB_FRAMES, sizeof(struct rvce_cpb_slot));
+ if (!enc->cpb_array)
+ goto error;
+
+ reset_cpb(enc);
+
radeon_vce_40_2_2_init(enc);
return &enc->base;
@@ -278,6 +352,7 @@ error:
rvid_destroy_buffer(&enc->cpb);
+ FREE(enc->cpb_array);
FREE(enc);
return NULL;
}
diff --git a/src/gallium/drivers/radeon/radeon_vce.h b/src/gallium/drivers/radeon/radeon_vce.h
index 3ea738b..f815cad 100644
--- a/src/gallium/drivers/radeon/radeon_vce.h
+++ b/src/gallium/drivers/radeon/radeon_vce.h
@@ -34,6 +34,8 @@
#ifndef RADEON_VCE_H
#define RADEON_VCE_H
+#include "util/u_double_list.h"
+
#define RVCE_RELOC(buf, usage, domain) (enc->ws->cs_add_reloc(enc->cs, (buf), (usage), domain, RADEON_PRIO_MIN))
#define RVCE_CS(value) (enc->cs->buf[enc->cs->cdw++] = (value))
@@ -52,6 +54,16 @@ typedef void (*rvce_get_buffer)(struct pipe_resource *resource,
struct radeon_winsys_cs_handle **handle,
struct radeon_surface **surface);
+/* Coded picture buffer slot */
+struct rvce_cpb_slot {
+ struct list_head list;
+
+ unsigned index;
+ enum pipe_h264_enc_picture_type picture_type;
+ unsigned frame_num;
+ unsigned pic_order_cnt;
+};
+
/* VCE encoder representation */
struct rvce_encoder {
struct pipe_video_codec base;
@@ -82,6 +94,9 @@ struct rvce_encoder {
struct radeon_winsys_cs_handle* bs_handle;
unsigned bs_size;
+ struct rvce_cpb_slot *cpb_array;
+ struct list_head cpb_slots;
+
struct rvid_buffer *fb;
struct rvid_buffer cpb;
struct pipe_h264_enc_picture_desc pic;
diff --git a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
index 33a58f3..1327d64 100644
--- a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
+++ b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
@@ -44,6 +44,27 @@
#include "radeon_video.h"
#include "radeon_vce.h"
+static struct rvce_cpb_slot *current_slot(struct rvce_encoder *enc)
+{
+ return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.prev, list);
+}
+
+static struct rvce_cpb_slot *l0_slot(struct rvce_encoder *enc)
+{
+ return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.next, list);
+}
+
+static void frame_offset(struct rvce_encoder *enc, struct rvce_cpb_slot *slot,
+ unsigned *luma_offset, unsigned *chroma_offset)
+{
+ unsigned pitch = align(enc->luma->level[0].pitch_bytes, 128);
+ unsigned vpitch = align(enc->luma->npix_y, 16);
+ unsigned fsize = pitch * (vpitch + vpitch / 2);
+
+ *luma_offset = slot->index * fsize;
+ *chroma_offset = *luma_offset + pitch * vpitch;
+}
+
static void session(struct rvce_encoder *enc)
{
RVCE_BEGIN(0x00000001); // session cmd
@@ -218,17 +239,6 @@ static void rdo(struct rvce_encoder *enc)
RVCE_END();
}
-static void frame_offset(struct rvce_encoder *enc, unsigned frame_num,
- unsigned *luma_offset, unsigned *chroma_offset)
-{
- unsigned pitch = align(enc->luma->level[0].pitch_bytes, 128);
- unsigned vpitch = align(enc->luma->npix_y, 16);
- unsigned fsize = pitch * (vpitch + vpitch / 2);
-
- *luma_offset = (frame_num % RVCE_NUM_CPB_FRAMES) * fsize;
- *chroma_offset = *luma_offset + pitch * vpitch;
-}
-
static void encode(struct rvce_encoder *enc)
{
int i;
@@ -297,11 +307,11 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0xffffffff); // chromaOffset
}
else if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P) {
- frame_offset(enc, enc->pic.ref_idx_l0, &luma_offset, &chroma_offset);
- RVCE_CS(0x00000000); // encPicType
- // TODO: Stores these in the CPB backtrack
- RVCE_CS(enc->pic.frame_num - 1); // frameNumber
- RVCE_CS(enc->pic.frame_num - 1); // pictureOrderCount
+ struct rvce_cpb_slot *l0 = l0_slot(enc);
+ frame_offset(enc, l0, &luma_offset, &chroma_offset);
+ RVCE_CS(l0->picture_type); // encPicType
+ RVCE_CS(l0->frame_num); // frameNumber
+ RVCE_CS(l0->pic_order_cnt); // pictureOrderCount
RVCE_CS(luma_offset); // lumaOffset
RVCE_CS(chroma_offset); // chromaOffset
}
@@ -314,7 +324,7 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0xffffffff); // chromaOffset
}
- frame_offset(enc, enc->pic.frame_num, &luma_offset, &chroma_offset);
+ frame_offset(enc, current_slot(enc), &luma_offset, &chroma_offset);
RVCE_CS(luma_offset); // encReconstructedLumaOffset
RVCE_CS(chroma_offset); // encReconstructedChromaOffset
RVCE_CS(0x00000000); // encColocBufferOffset
commit d7d41ce133fa7369f7a5ea12bfc971c5ecafb3ba
Author: Christian König <christian.koenig@amd.com>
Date: Fri Apr 4 14:22:16 2014 +0200
vl: add interface for H264 B-frame encoding
Signed-off-by: Christian König <christian.koenig@amd.com>
diff --git a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
index c41b2d0..33a58f3 100644
--- a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
+++ b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
@@ -156,8 +156,8 @@ static void pic_control(struct rvce_encoder *enc)
RVCE_CS(0x00000040); // encConstraintSetFlags
RVCE_CS(0x00000000); // encBPicPattern
RVCE_CS(0x00000000); // weightPredModeBPicture
- RVCE_CS(0x00000001); // encNumberOfReferenceFrames
- RVCE_CS(0x00000001); // encMaxNumRefFrames
+ RVCE_CS(MIN2(enc->base.max_references, 2)); // encNumberOfReferenceFrames
+ RVCE_CS(enc->base.max_references + 1); // encMaxNumRefFrames
RVCE_CS(0x00000000); // encNumDefaultActiveRefL0
RVCE_CS(0x00000000); // encNumDefaultActiveRefL1
RVCE_CS(0x00000000); // encSliceMode
@@ -297,8 +297,9 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0xffffffff); // chromaOffset
}
else if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P) {
- frame_offset(enc, enc->pic.frame_num - 1, &luma_offset, &chroma_offset);
+ frame_offset(enc, enc->pic.ref_idx_l0, &luma_offset, &chroma_offset);
RVCE_CS(0x00000000); // encPicType
+ // TODO: Stores these in the CPB backtrack
RVCE_CS(enc->pic.frame_num - 1); // frameNumber
RVCE_CS(enc->pic.frame_num - 1); // pictureOrderCount
RVCE_CS(luma_offset); // lumaOffset
@@ -322,8 +323,8 @@ static void encode(struct rvce_encoder *enc)
RVCE_CS(0x00000000); // encReferenceRefBasePictureLumaOffset
RVCE_CS(0x00000000); // encReferenceRefBasePictureChromaOffset
RVCE_CS(0x00000000); // pictureCount
- RVCE_CS(0x00000000); // frameNumber
- RVCE_CS(0x00000000); // pictureOrderCount
+ RVCE_CS(enc->pic.frame_num); // frameNumber
+ RVCE_CS(enc->pic.pic_order_cnt); // pictureOrderCount
RVCE_CS(0x00000000); // numIPicRemainInRCGOP
RVCE_CS(0x00000000); // numPPicRemainInRCGOP
RVCE_CS(0x00000000); // numBPicRemainInRCGOP
diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h
index f9721dc..0256a8f 100644
--- a/src/gallium/include/pipe/p_video_state.h
+++ b/src/gallium/include/pipe/p_video_state.h
@@ -368,6 +368,9 @@ struct pipe_h264_enc_picture_desc
enum pipe_h264_enc_picture_type picture_type;
unsigned frame_num;
+ unsigned pic_order_cnt;
+ unsigned ref_idx_l0;
+ unsigned ref_idx_l1;
};
#ifdef __cplusplus
diff --git a/src/gallium/state_trackers/omx/vid_enc.c b/src/gallium/state_trackers/omx/vid_enc.c
index 8ec0439..080730b 100644
--- a/src/gallium/state_trackers/omx/vid_enc.c
+++ b/src/gallium/state_trackers/omx/vid_enc.c
@@ -769,11 +769,17 @@ static void enc_ControlPicture(omx_base_PortType *port,
if (!(priv->frame_num % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || priv->force_pic_type.IntraRefreshVOP) {
picture->picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR;
+ picture->ref_idx_l0 = 0;
+ picture->ref_idx_l1 = 0;
priv->frame_num = 0;
- } else
+ } else {
picture->picture_type = PIPE_H264_ENC_PICTURE_TYPE_P;
+ picture->ref_idx_l0 = priv->frame_num - 1;
+ picture->ref_idx_l1 = 0;
+ }
picture->frame_num = priv->frame_num++;
+ picture->pic_order_cnt = picture->frame_num;
priv->force_pic_type.IntraRefreshVOP = OMX_FALSE;
}
commit ee4439c562e88446b94fbb98e9d02ad105efc01e
Author: Christian König <christian.koenig@amd.com>
Date: Mon Apr 7 17:26:31 2014 +0200
radeon/vce: remove RVCE_NUM_CPB_EXTRA_FRAMES
Doesn't seems to be needed any more.
Signed-off-by: Christian König <christian.koenig@amd.com>
diff --git a/src/gallium/drivers/radeon/radeon_vce.c b/src/gallium/drivers/radeon/radeon_vce.c
index 4b824f9..012b4f8 100644
--- a/src/gallium/drivers/radeon/radeon_vce.c
+++ b/src/gallium/drivers/radeon/radeon_vce.c
@@ -262,7 +262,7 @@ struct pipe_video_codec *rvce_create_encoder(struct pipe_context *context,
vpitch = align(tmp_surf->npix_y, 16);
tmp_buf->destroy(tmp_buf);
if (!rvid_create_buffer(enc->ws, &enc->cpb,
- pitch * vpitch * 1.5 * (RVCE_NUM_CPB_FRAMES + RVCE_NUM_CPB_EXTRA_FRAMES),
+ pitch * vpitch * 1.5 * RVCE_NUM_CPB_FRAMES,
RADEON_DOMAIN_VRAM)) {
RVID_ERR("Can't create CPB buffer.\n");
goto error;
diff --git a/src/gallium/drivers/radeon/radeon_vce.h b/src/gallium/drivers/radeon/radeon_vce.h
index 9dc0c68..3ea738b 100644
--- a/src/gallium/drivers/radeon/radeon_vce.h
+++ b/src/gallium/drivers/radeon/radeon_vce.h
@@ -44,7 +44,6 @@
#define RVCE_END() *begin = (&enc->cs->buf[enc->cs->cdw] - begin) * 4; }
#define RVCE_NUM_CPB_FRAMES 2
-#define RVCE_NUM_CPB_EXTRA_FRAMES 2
struct r600_common_screen;
diff --git a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
index 26c3629..c41b2d0 100644
--- a/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
+++ b/src/gallium/drivers/radeon/radeon_vce_40_2_2.c
@@ -224,9 +224,8 @@ static void frame_offset(struct rvce_encoder *enc, unsigned frame_num,
unsigned pitch = align(enc->luma->level[0].pitch_bytes, 128);
unsigned vpitch = align(enc->luma->npix_y, 16);
unsigned fsize = pitch * (vpitch + vpitch / 2);
- unsigned base_offset = RVCE_NUM_CPB_EXTRA_FRAMES * fsize;
- *luma_offset = base_offset + (frame_num % RVCE_NUM_CPB_FRAMES) * fsize;
+ *luma_offset = (frame_num % RVCE_NUM_CPB_FRAMES) * fsize;
*chroma_offset = *luma_offset + pitch * vpitch;
}
commit ce57c8e925a378593b77f04d19c395a7f1c8f82e
Author: Chris Forbes <chrisf@ijw.co.nz>
Date: Fri Apr 11 21:20:13 2014 +1200
docs/relnotes: Fix consistency, add i965 to ARB_buffer_storage.
Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
diff --git a/docs/relnotes/10.2.html b/docs/relnotes/10.2.html
index 5b93685..d7d557b 100644
--- a/docs/relnotes/10.2.html
+++ b/docs/relnotes/10.2.html
@@ -44,9 +44,9 @@ Note: some of the new features are only available with certain drivers.
</p>
<ul>
-<li>GL_ARB_buffer_storage on r300, r600, and radeonsi</li>
+<li>GL_ARB_buffer_storage on i965, r300, r600, and radeonsi</li>
<li>GL_ARB_stencil_texturing on i965/gen8+</li>
-<li>ARB_texture_view on i965/gen7</li>
+<li>GL_ARB_texture_view on i965/gen7</li>
</ul>
commit 227049098b59bca88883a750602fdad41949c996
Author: Kenneth Graunke <kenneth@whitecape.org>
Date: Wed Apr 9 22:54:11 2014 -0700
i965: Fix missing _NEW_SCISSOR in Broadwell SF_CLIP_VIEWPORT state.
The _Xmin/_Xmax/_Ymin/_Ymax values need to be guarded by _NEW_SCISSOR.
Fixes Piglit's scissor-many, and rendering in GNOME Shell.
Hopefully fixes similar issues with Unity and ChromeOS.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75879
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Tested-by: James Ausmus <james.ausmus@intel.com>
Tested-by: Timo Aaltonen <tjaalton@ubuntu.com>
diff --git a/src/mesa/drivers/dri/i965/gen8_viewport_state.c b/src/mesa/drivers/dri/i965/gen8_viewport_state.c
index 344310e..b366246 100644
--- a/src/mesa/drivers/dri/i965/gen8_viewport_state.c
+++ b/src/mesa/drivers/dri/i965/gen8_viewport_state.c
@@ -86,7 +86,7 @@ gen8_upload_sf_clip_viewport(struct brw_context *brw)
vp[10] = -gby; /* y-min */
vp[11] = gby; /* y-max */
- /* Screen Space Viewport */
+ /* _NEW_SCISSOR | _NEW_VIEWPORT | _NEW_BUFFERS: Screen Space Viewport */
if (render_to_fbo) {
vp[12] = ctx->DrawBuffer->_Xmin;
vp[13] = ctx->DrawBuffer->_Xmax - 1;
@@ -110,7 +110,7 @@ gen8_upload_sf_clip_viewport(struct brw_context *brw)
const struct brw_tracked_state gen8_sf_clip_viewport = {
.dirty = {
- .mesa = _NEW_VIEWPORT | _NEW_BUFFERS,
+ .mesa = _NEW_BUFFERS | _NEW_SCISSOR | _NEW_VIEWPORT,
.brw = BRW_NEW_BATCH,
Reply to: