pnw_cmdbuf.c revision f91c8768670386683a281cc39141e21bdda9c97f
1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Waldo Bastian <waldo.bastian@intel.com>
27 *    Zeng Li <zeng.li@intel.com>
28 *
29 */
30
31
32#include "pnw_cmdbuf.h"
33
34#include <unistd.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <errno.h>
38#include <string.h>
39#include <wsbm/wsbm_manager.h>
40
41#include "psb_def.h"
42#include "pnw_hostcode.h"
43#include "psb_ws_driver.h"
44#include "psb_drm.h"
45
46/*
47 * Buffer layout:
48 *         cmd_base <= cmd_idx < CMD_END() == reloc_base
49 *         reloc_base <= reloc_idx < RELOC_END() == (reloc_size)
50 */
51
52#define RELOC_END(cmdbuf)     (cmdbuf->cmd_base + cmdbuf->size)
53
54#define CMD_END(cmdbuf)       (cmdbuf->reloc_base)
55
56#define RELOC_SIZE            (0x3000)
57
58#define CMD_SIZE              (0x3000)
59
60#define RELOC_MARGIN          (0x0800)
61
62#define CMD_MARGIN            (0x0400)
63
64
65#define MAX_CMD_COUNT         12
66
67#define MTX_SEG_SIZE          (0x0800)
68
69
70/*
71 * Create command buffer
72 */
73VAStatus pnw_cmdbuf_create(
74    object_context_p obj_context,
75    psb_driver_data_p driver_data,
76    pnw_cmdbuf_p cmdbuf)
77{
78    context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
79    VAStatus vaStatus = VA_STATUS_SUCCESS;
80    unsigned int size = CMD_SIZE + RELOC_SIZE;
81
82    cmdbuf->size = 0;
83    cmdbuf->cmd_base = NULL;
84    cmdbuf->cmd_idx = NULL;
85    cmdbuf->reloc_base = NULL;
86    cmdbuf->reloc_idx = NULL;
87    cmdbuf->buffer_refs_count = 0;
88    cmdbuf->buffer_refs_allocated = 10;
89    cmdbuf->buffer_refs = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
90    if (NULL == cmdbuf->buffer_refs) {
91        cmdbuf->buffer_refs_allocated = 0;
92        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
93    }
94    if (VA_STATUS_SUCCESS == vaStatus) {
95        vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_only, &cmdbuf->buf);
96        cmdbuf->size = size;
97    }
98
99    if (VA_STATUS_SUCCESS != vaStatus) {
100        free(cmdbuf->buffer_refs);
101        cmdbuf->buffer_refs = NULL;
102        cmdbuf->buffer_refs_allocated = 0;
103        return vaStatus;
104    }
105
106    /* create topaz parameter buffer */
107    vaStatus = psb_buffer_create(driver_data, ctx->pic_params_size * MAX_TOPAZ_CORES, psb_bt_cpu_vpu, &cmdbuf->pic_params);
108    if (VA_STATUS_SUCCESS != vaStatus)
109        goto error_out5;
110
111    /* create header buffer */
112    vaStatus = psb_buffer_create(driver_data, ctx->header_buffer_size, psb_bt_cpu_vpu, &cmdbuf->header_mem);
113    if (VA_STATUS_SUCCESS != vaStatus)
114        goto error_out2;
115
116    /* create slice parameter buffer */
117    vaStatus = psb_buffer_create(driver_data, ctx->sliceparam_buffer_size, psb_bt_cpu_vpu, &cmdbuf->slice_params);
118    if (VA_STATUS_SUCCESS != vaStatus)
119        goto error_out1;
120
121    /* all cmdbuf share one MTX_CURRENT_IN_PARAMS since every MB has a MTX_CURRENT_IN_PARAMS structure
122     * and filling this structure for all MB is very time-consuming
123     */
124
125    cmdbuf->topaz_in_params_I = &ctx->topaz_in_params_I;
126    cmdbuf->topaz_in_params_P = &ctx->topaz_in_params_P;
127
128    cmdbuf->topaz_below_params = &ctx->topaz_below_params;
129    cmdbuf->topaz_above_params = &ctx->topaz_above_params;
130
131    return vaStatus;
132
133error_out1:
134    psb_buffer_destroy(&cmdbuf->header_mem);
135error_out2:
136    psb_buffer_destroy(&cmdbuf->pic_params);
137error_out5:
138    pnw_cmdbuf_destroy(cmdbuf);
139
140    return vaStatus;
141}
142
143/*
144 * Destroy buffer
145 */
146void pnw_cmdbuf_destroy(pnw_cmdbuf_p cmdbuf)
147{
148    if (cmdbuf->size) {
149        psb_buffer_destroy(&cmdbuf->buf);
150        cmdbuf->size = 0;
151    }
152    if (cmdbuf->buffer_refs_allocated) {
153        free(cmdbuf->buffer_refs);
154        cmdbuf->buffer_refs = NULL;
155        cmdbuf->buffer_refs_allocated = 0;
156    }
157
158    psb_buffer_destroy(&cmdbuf->pic_params);
159    psb_buffer_destroy(&cmdbuf->header_mem);
160    psb_buffer_destroy(&cmdbuf->slice_params);
161
162}
163
164/*
165 * Reset buffer & map
166 *
167 * Returns 0 on success
168 */
169int pnw_cmdbuf_reset(pnw_cmdbuf_p cmdbuf)
170{
171    int ret;
172
173    cmdbuf->cmd_base = NULL;
174    cmdbuf->cmd_idx = NULL;
175    cmdbuf->reloc_base = NULL;
176    cmdbuf->reloc_idx = NULL;
177
178    cmdbuf->buffer_refs_count = 0;
179    cmdbuf->cmd_count = 0;
180
181    ret = psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base);
182    if (ret) {
183        return ret;
184    }
185
186    cmdbuf->cmd_start = cmdbuf->cmd_base;
187    cmdbuf->cmd_idx = (uint32_t *) cmdbuf->cmd_base;
188
189    cmdbuf->reloc_base = cmdbuf->cmd_base + CMD_SIZE;
190    cmdbuf->reloc_idx = (struct drm_psb_reloc *) cmdbuf->reloc_base;
191
192    /* Add ourselves to the buffer list */
193    pnw_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->buf); /* cmd buf == 0 */
194    return ret;
195}
196
197/*
198 * Unmap buffer
199 *
200 * Returns 0 on success
201 */
202int pnw_cmdbuf_unmap(pnw_cmdbuf_p cmdbuf)
203{
204    cmdbuf->cmd_base = NULL;
205    cmdbuf->cmd_start = NULL;
206    cmdbuf->cmd_idx = NULL;
207    cmdbuf->reloc_base = NULL;
208    cmdbuf->reloc_idx = NULL;
209    cmdbuf->cmd_count = 0;
210    psb_buffer_unmap(&cmdbuf->buf);
211    return 0;
212}
213
214
215/*
216 * Reference an addtional buffer "buf" in the command stream
217 * Returns a reference index that can be used to refer to "buf" in
218 * relocation records, -1 on error
219 */
220int pnw_cmdbuf_buffer_ref(pnw_cmdbuf_p cmdbuf, psb_buffer_p buf)
221{
222    int item_loc = 0;
223
224    /*Reserve the same TTM BO twice will cause kernel lock up*/
225    while ((item_loc < cmdbuf->buffer_refs_count)
226           && (wsbmKBufHandle(wsbmKBuf(cmdbuf->buffer_refs[item_loc]->drm_buf))
227               != wsbmKBufHandle(wsbmKBuf(buf->drm_buf))))
228        //while( (item_loc < cmdbuf->buffer_refs_count) && (cmdbuf->buffer_refs[item_loc] != buf) )
229    {
230        item_loc++;
231    }
232    if (item_loc == cmdbuf->buffer_refs_count) {
233        /* Add new entry */
234        if (item_loc >= cmdbuf->buffer_refs_allocated) {
235            /* Allocate more entries */
236            int new_size = cmdbuf->buffer_refs_allocated + 10;
237            psb_buffer_p *new_array;
238            new_array = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * new_size);
239            if (NULL == new_array) {
240                return -1; /* Allocation failure */
241            }
242            memcpy(new_array, cmdbuf->buffer_refs, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
243            free(cmdbuf->buffer_refs);
244            cmdbuf->buffer_refs_allocated = new_size;
245            cmdbuf->buffer_refs = new_array;
246        }
247        cmdbuf->buffer_refs[item_loc] = buf;
248        cmdbuf->buffer_refs_count++;
249        buf->status = psb_bs_queued;
250    }
251    return item_loc;
252}
253
254/* Creates a relocation record for a DWORD in the mapped "cmdbuf" at address
255 * "addr_in_cmdbuf"
256 * The relocation is based on the device virtual address of "ref_buffer"
257 * "buf_offset" is be added to the device virtual address, and the sum is then
258 * right shifted with "align_shift".
259 * "mask" determines which bits of the target DWORD will be updated with the so
260 * constructed address. The remaining bits will be filled with bits from "background".
261 */
262void pnw_cmdbuf_add_relocation(pnw_cmdbuf_p cmdbuf,
263                               uint32_t *addr_in_dst_buffer,/*addr of dst_buffer for the DWORD*/
264                               psb_buffer_p ref_buffer,
265                               uint32_t buf_offset,
266                               uint32_t mask,
267                               uint32_t background,
268                               uint32_t align_shift,
269                               uint32_t dst_buffer,
270                               uint32_t *start_of_dst_buffer) /*Index of the list refered by cmdbuf->buffer_refs */
271{
272    struct drm_psb_reloc *reloc = cmdbuf->reloc_idx;
273    uint64_t presumed_offset = wsbmBOOffsetHint(ref_buffer->drm_buf);
274
275    reloc->where = addr_in_dst_buffer - start_of_dst_buffer; /* Offset in DWORDs */
276
277    reloc->buffer = pnw_cmdbuf_buffer_ref(cmdbuf, ref_buffer);
278    ASSERT(reloc->buffer != -1);
279
280    reloc->reloc_op = PSB_RELOC_OP_OFFSET;
281#ifndef VA_EMULATOR
282    if (presumed_offset) {
283        uint32_t new_val =  presumed_offset + buf_offset;
284
285        new_val = ((new_val >> align_shift) << (align_shift << PSB_RELOC_ALSHIFT_SHIFT));
286        new_val = (background & ~mask) | (new_val & mask);
287        *addr_in_dst_buffer = new_val;
288    } else {
289        *addr_in_dst_buffer = PSB_RELOC_MAGIC;
290    }
291#else
292    /* indicate subscript of relocation buffer */
293    *addr_in_dst_buffer = reloc - (struct drm_psb_reloc *)cmdbuf->reloc_base;
294#endif
295    reloc->mask = mask;
296    reloc->shift = align_shift << PSB_RELOC_ALSHIFT_SHIFT;
297    reloc->pre_add = buf_offset;
298    reloc->background = background;
299    reloc->dst_buffer = dst_buffer;
300    cmdbuf->reloc_idx++;
301
302    ASSERT(((void *)(cmdbuf->reloc_idx)) < RELOC_END(cmdbuf));
303}
304
305/* Prepare one command package */
306void pnw_cmdbuf_insert_command_package(object_context_p obj_context,
307                                       int32_t core,
308                                       uint32_t cmd_id,
309                                       psb_buffer_p command_data,
310                                       uint32_t offset)
311{
312    uint32_t cmd_word;
313    context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
314    pnw_cmdbuf_p cmdbuf = obj_context->pnw_cmdbuf;
315    int interrupt_flags;
316
317    /* only MTX_CMDID_END_PIC by master core generate interrupt */
318    interrupt_flags = (cmd_id == MTX_CMDID_END_PIC) | (core == 0);
319    interrupt_flags = 0; /*CMD composed by user space does not generate Interrupt*/
320
321    /* Calculate command word */
322    cmd_id &= MTX_CMDWORD_ID_MASK;
323    core &= MTX_CMDWORD_CORE_MASK;
324
325    core %= MAX_TOPAZ_CORES;
326
327    cmd_word = ((ctx->CmdCount & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT)
328               | ((0 & MTX_CMDWORD_INT_MASK) << MTX_CMDWORD_INT_SHIFT) /* Do not generate interrupt */
329               | (core << MTX_CMDWORD_CORE_SHIFT)
330               | (cmd_id << MTX_CMDWORD_ID_SHIFT);
331
332    /* write command word into cmdbuf */
333    *cmdbuf->cmd_idx++ = cmd_word;
334
335    /* Command data address */
336    if (command_data) {
337        RELOC_CMDBUF_PNW(cmdbuf->cmd_idx, offset, command_data);
338        cmdbuf->cmd_idx++;
339    } else {
340        *cmdbuf->cmd_idx++ = 0;
341    }
342
343
344    *cmdbuf->cmd_idx++ = 0;             /* Write back buffer address */
345
346    *cmdbuf->cmd_idx++ = 0; /*ctx->CmdCount; */ /* Write back value */
347
348    ctx->LastSync[(ctx->FrmIdx) & 0x1][core] = ctx->CmdCount;
349
350    /* increment the command counter */
351    ctx->CmdCount = (ctx->CmdCount + 1) % MAX_TOPAZ_CMD_COUNT;
352}
353
354/*
355 * Advances "obj_context" to the next cmdbuf
356 *
357 * Returns 0 on success
358 */
359int pnw_context_get_next_cmdbuf(object_context_p obj_context)
360{
361    pnw_cmdbuf_p cmdbuf;
362    int ret;
363
364    if (obj_context->pnw_cmdbuf) {
365        return 0;
366    }
367
368    obj_context->cmdbuf_current++;
369    if (obj_context->cmdbuf_current >= PNW_MAX_CMDBUFS_ENCODE) {
370        obj_context->cmdbuf_current = 0;
371    }
372
373    cmdbuf = obj_context->pnw_cmdbuf_list[obj_context->cmdbuf_current];
374    ret = pnw_cmdbuf_reset(cmdbuf);
375    if (!ret) {
376        /* Success */
377        obj_context->pnw_cmdbuf = cmdbuf;
378    }
379
380    /* added pic_params/slice_params into ref, so the index is 1/2 */
381    pnw_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->pic_params);
382    pnw_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->slice_params);
383
384    return ret;
385}
386
387/*
388 * This is the user-space do-it-all interface to the drm cmdbuf ioctl.
389 * It allows different buffers as command- and reloc buffer. A list of
390 * cliprects to apply and whether to copy the clipRect content to all
391 * scanout buffers (damage = 1).
392 */
393/*
394 * Don't add debug statements in this function, it gets called with the
395 * DRM lock held and output to an X terminal can cause X to deadlock
396 */
397static int
398pnwDRMCmdBuf(int fd, int ioctl_offset, psb_buffer_p *buffer_list, int buffer_count, unsigned cmdBufHandle,
399             unsigned cmdBufOffset, unsigned cmdBufSize,
400             unsigned relocBufHandle, unsigned relocBufOffset,
401             unsigned numRelocs, drm_clip_rect_t * clipRects, int damage,
402             unsigned engine, unsigned fence_flags, struct psb_ttm_fence_rep *fence_rep)
403{
404    drm_psb_cmdbuf_arg_t ca;
405    struct psb_validate_arg *arg_list;
406    int i;
407    int ret;
408    uint64_t mask = PSB_GPU_ACCESS_MASK;
409
410    arg_list = (struct psb_validate_arg *) calloc(1, sizeof(struct psb_validate_arg) * buffer_count);
411    if (arg_list == NULL) {
412        psb__error_message("Allocate memory failed\n");
413        return -ENOMEM;
414    }
415
416    for (i = 0; i < buffer_count; i++) {
417        struct psb_validate_arg *arg = &(arg_list[i]);
418        struct psb_validate_req *req = &arg->d.req;
419
420        memset(arg, 0, sizeof(*arg));
421        req->next = (unsigned long) & (arg_list[i+1]);
422
423        req->buffer_handle = wsbmKBufHandle(wsbmKBuf(buffer_list[i]->drm_buf));
424        req->group = 0;
425        req->set_flags = (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) & mask;
426        req->clear_flags = (~(PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)) & mask;
427#if 1
428        req->presumed_gpu_offset = (uint64_t)wsbmBOOffsetHint(buffer_list[i]->drm_buf);
429        req->presumed_flags = PSB_USE_PRESUMED;
430        if ((req->presumed_gpu_offset >> 28) & 0x1) {
431            psb__error_message("buffer is at the address topaz can not access\n");
432            ret = -1;
433            goto out;
434        }
435#else
436        req->presumed_flags = 0;
437#endif
438        req->pad64 = (uint32_t)buffer_list[i]->pl_flags;
439    }
440    arg_list[buffer_count-1].d.req.next = 0;
441
442    memset(&ca, 0, sizeof(ca));
443
444    ca.buffer_list = (uint64_t)((unsigned long)arg_list);
445    ca.clip_rects = (uint64_t)((unsigned long)clipRects);
446    ca.cmdbuf_handle = cmdBufHandle;
447    ca.cmdbuf_offset = cmdBufOffset;
448    ca.cmdbuf_size = cmdBufSize;
449    ca.reloc_handle = relocBufHandle;
450    ca.reloc_offset = relocBufOffset;
451    ca.num_relocs = numRelocs;
452    ca.engine = engine;
453    ca.fence_flags = fence_flags;
454    ca.fence_arg = (uint64_t)((unsigned long)fence_rep);
455    ca.damage = damage;
456
457
458    do {
459        ret = drmCommandWrite(fd, ioctl_offset, &ca, sizeof(ca));
460    } while (ret == EAGAIN);
461
462    if (ret)
463        goto out;
464
465    for (i = 0; i < buffer_count; i++) {
466        struct psb_validate_arg *arg = &(arg_list[i]);
467        struct psb_validate_rep *rep = &arg->d.rep;
468
469        if (!arg->handled) {
470            ret = -EFAULT;
471            goto out;
472        }
473        if (arg->ret != 0) {
474            ret = arg->ret;
475            goto out;
476        }
477        wsbmUpdateKBuf(wsbmKBuf(buffer_list[i]->drm_buf),
478                       rep->gpu_offset, rep->placement, rep->fence_type_mask);
479    }
480out:
481    free(arg_list);
482    for (i = 0; i < buffer_count; i++) {
483        /*
484         * Buffer no longer queued in userspace
485         */
486        switch (buffer_list[i]->status) {
487        case psb_bs_queued:
488            buffer_list[i]->status = psb_bs_ready;
489            break;
490
491        case psb_bs_abandoned:
492            psb_buffer_destroy(buffer_list[i]);
493            free(buffer_list[i]);
494            break;
495
496        default:
497            /* Not supposed to happen */
498            ASSERT(0);
499        }
500    }
501
502    return ret;
503}
504
505#if 0
506static struct _WsbmFenceObject *
507lnc_fence_wait(psb_driver_data_p driver_data,
508               struct psb_ttm_fence_rep *fence_rep, int *status)
509
510{
511    struct _WsbmFenceObject *fence = NULL;
512    int ret = -1;
513
514    /* copy fence information */
515    if (fence_rep->error != 0) {
516        psb__error_message("drm failed to create a fence"
517                           " and has idled the HW\n");
518        DEBUG_FAILURE_RET;
519        return NULL;
520    }
521
522    fence = wsbmFenceCreate(driver_data->fence_mgr, fence_rep->fence_class,
523                            fence_rep->fence_type,
524                            (void *)fence_rep->handle,
525                            0);
526    if (fence)
527        *status = wsbmFenceFinish(fence, fence_rep->fence_type, 0);
528
529    return fence;
530}
531#endif
532
533/*
534 * Submits the current cmdbuf
535 *
536 * Returns 0 on success
537 */
538int pnw_context_submit_cmdbuf(object_context_p obj_context)
539{
540
541    return 0;
542}
543
544
545
546/*
547 * FrameSkip is only meaningful for RC enabled mode
548 * Topaz raises this flag after surface N encoding is finished (vaSyncSurface gets back)
549 * then for the next encode surface N+1 (ctx->src_surface) frameskip flag is cleared in vaBeginPicuture
550 * and is always set in vaEndPicture:lnc_PatchRCMode
551 * vaQuerySurfaceStatus is supposed only to be called after vaEndPicture/vaSyncSurface,
552 * The caller should ensure the surface pertains to an encode context
553 */
554int pnw_surface_get_frameskip(psb_driver_data_p driver_data,
555                              psb_surface_p surface,
556                              int *frame_skip)
557{
558    /* bit31 indicate if frameskip is already settled, it is used to record the frame skip flag for old surfaces
559     * bit31 is cleared when the surface is used as encode render target or reference/reconstrucure target
560     */
561    if (GET_SURFACE_INFO_skipped_flag(surface) & SURFACE_INFO_SKIP_FLAG_SETTLED) {
562        *frame_skip = GET_SURFACE_INFO_skipped_flag(surface) & 1;
563    } else
564        *frame_skip = 0;
565
566    return 0;
567}
568
569
570/*
571 * Flushes all cmdbufs
572 */
573int pnw_context_flush_cmdbuf(object_context_p obj_context)
574{
575    pnw_cmdbuf_p cmdbuf = obj_context->pnw_cmdbuf;
576    psb_driver_data_p driver_data = obj_context->driver_data;
577    unsigned int fence_flags;
578    struct psb_ttm_fence_rep fence_rep;
579    unsigned int reloc_offset;
580    unsigned int num_relocs;
581    int ret;
582    unsigned int cmdbuffer_size = (void *) cmdbuf->cmd_idx - cmdbuf->cmd_start; /* In bytes */
583
584    ASSERT(cmdbuffer_size < CMD_SIZE);
585    ASSERT((void *) cmdbuf->cmd_idx < CMD_END(cmdbuf));
586    /* LOCK */
587    ret = LOCK_HARDWARE(driver_data);
588    if (ret) {
589        UNLOCK_HARDWARE(driver_data);
590        DEBUG_FAILURE_RET;
591        return ret;
592    }
593
594    /* Now calculate the total number of relocations */
595    reloc_offset = cmdbuf->reloc_base - cmdbuf->cmd_base;
596    num_relocs = (((void *) cmdbuf->reloc_idx) - cmdbuf->reloc_base) / sizeof(struct drm_psb_reloc);
597
598    pnw_cmdbuf_unmap(cmdbuf);
599
600    ASSERT(NULL == cmdbuf->reloc_base);
601
602#ifdef DEBUG_TRACE
603    fence_flags = 0;
604#else
605    fence_flags = DRM_PSB_FENCE_NO_USER;
606#endif
607
608#ifndef LNC_ENGINE_ENCODE
609#define LNC_ENGINE_ENCODE  5
610#endif
611
612    wsbmWriteLockKernelBO();
613    ret = pnwDRMCmdBuf(driver_data->drm_fd, driver_data->execIoctlOffset, /* FIXME Still use ioctl cmd? */
614                       cmdbuf->buffer_refs, cmdbuf->buffer_refs_count, wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)),
615                       0, cmdbuffer_size,/*unsigned cmdBufSize*/
616                       wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)), reloc_offset, num_relocs,
617                       0 /* clipRects */, 0, LNC_ENGINE_ENCODE, fence_flags, &fence_rep); /* FIXME use LNC_ENGINE_ENCODE */
618
619    wsbmWriteUnlockKernelBO();
620    UNLOCK_HARDWARE(driver_data);
621
622    if (ret) {
623        obj_context->pnw_cmdbuf = NULL;
624
625        DEBUG_FAILURE_RET;
626        return ret;
627    }
628
629#if 0 /*DEBUG_TRACE*/
630    int status = -1;
631    struct _WsbmFenceObject *fence = NULL;
632
633    fence = lnc_fence_wait(driver_data, &fence_rep, &status);
634    psb__information_message("psb_fence_wait returns: %d (fence=0x%08x)\n", status, fence);
635
636    if (fence)
637        wsbmFenceUnreference(fence);
638
639#endif
640
641    obj_context->pnw_cmdbuf = NULL;
642
643    return 0;
644}
645
646
647int pnw_get_parallel_core_number(object_context_p obj_context)
648{
649
650    context_ENC_p ctx = (context_ENC_p)(obj_context->format_data);
651    return ctx->ParallelCores;
652
653}
654