[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: