void* sbrk(long increment) { if (increment == 0) return memend; if (increment < 0) // >.> return memend; if (memend + increment <= pageend) { void* ret = memend; memend += increment; return ret; } size_t allocsize = ROUND_UP(increment, PAGE_SIZE); u32 taddr; if (Lv2Syscall3(348, allocsize, PAGE_SIZE_FLAG, (u64)&taddr)) { errno = ENOMEM; return (void*)-1; } char* addr = (char*)(u64)taddr; if (pageend != addr) memend = (char*)(u64)addr; pageend = addr + allocsize; char* ret = memend; memend += increment; return ret; }
static void __attribute__((constructor)) mallocsetup(void) { hts_lwmutex_init(&mutex); #ifdef USE_VIRTUAL_MEM int size = MB(256); int psize = MB(96); Lv2Syscall6(300, size, psize, 0xFFFFFFFFU, 0x200ULL, 1UL, (u64)&heap_base); #else int size = MB(96); Lv2Syscall3(348, size, 0x400, (u64)&heap_base); #endif total_avail = size; gpool = tlsf_create((void *)(intptr_t)heap_base, size); // Malloc is initialized now so we can safely do this http_path_add("/api/memstats", NULL, memstats, 1); }
static void waitFlip() { int i = 0; while(gcmGetFlipStatus() != 0) { i++; usleep(200); if(i == 10000) { TRACE(TRACE_ERROR, "GLW", "Flip never happend, system reboot"); Lv2Syscall3(379, 0x1200, 0, 0 ); gcmResetFlipStatus(); } } gcmResetFlipStatus(); }
static int video_ps3_vdec_codec_create(media_codec_t *mc, const media_codec_params_t *mcp, media_pipe_t *mp) { vdec_decoder_t *vdd; struct vdec_type dec_type = {0}; struct vdec_attr dec_attr = {0}; int spu_threads; int r; switch(mc->codec_id) { case AV_CODEC_ID_MPEG2VIDEO: if(!vdec_mpeg2_loaded) return no_lib(mp, "MPEG-2"); dec_type.codec_type = VDEC_CODEC_TYPE_MPEG2; dec_type.profile_level = VDEC_MPEG2_MP_HL; spu_threads = 1; break; case AV_CODEC_ID_H264: if(mcp != NULL) { if(mcp->profile == FF_PROFILE_H264_CONSTRAINED_BASELINE) return 1; // can't play this if(mcp->profile >= FF_PROFILE_H264_HIGH_10) return 1; // No 10bit support if(mcp->extradata != NULL) { h264_parser_t hp; hexdump("extradata", mcp->extradata, mcp->extradata_size); if(h264_parser_init(&hp, mcp->extradata, mcp->extradata_size)) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Cell-h264: Broken headers, Disabling acceleration")); return -1; } TRACE(TRACE_DEBUG, "VDEC", "Dumping SPS"); int too_big_refframes = 0; for(int i = 0; i < H264_PARSER_NUM_SPS; i++) { const h264_sps_t *s = &hp.sps_array[i]; if(!s->present) continue; TRACE(TRACE_DEBUG, "VDEC", "SPS[%d]: %d x %d profile:%d level:%d.%d ref-frames:%d", i, s->mb_width * 16, s->mb_height * 16, s->profile, s->level / 10, s->level % 10, s->num_ref_frames); if(s->mb_height >= 68 && s->num_ref_frames > 4) too_big_refframes = s->num_ref_frames; } h264_parser_fini(&hp); if(too_big_refframes) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Cell-h264: %d Ref-frames for 1080 content is incompatible with PS3 HW decoder. Disabling acceleration"), too_big_refframes); return -1; } } } if(!vdec_h264_loaded) return no_lib(mp, "h264"); dec_type.codec_type = VDEC_CODEC_TYPE_H264; if(mcp != NULL && mcp->level > 42) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Cell-h264: Forcing level 4.2 for content in level %d.%d. This may break video playback."), mcp->level / 10, mcp->level % 10); } dec_type.profile_level = 42; spu_threads = 4; break; default: return 1; } r = vdec_query_attr(&dec_type, &dec_attr); if(r) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to query Cell codec. Error 0x%x"), r); return 1; } vdd = calloc(1, sizeof(vdec_decoder_t)); #define ROUND_UP(p, round) ((p + round - 1) & ~(round - 1)) size_t allocsize = ROUND_UP(dec_attr.mem_size, 1024*1024); u32 taddr; if(Lv2Syscall3(348, allocsize, 0x400, (u64)&taddr)) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to open Cell codec. Unable to allocate %d bytes of RAM"), dec_attr.mem_size); return 1; } vdd->mem = (void *)(uint64_t)taddr; TRACE(TRACE_DEBUG, "VDEC", "Opening codec %s level %d using %d bytes of RAM", mc->codec_id == AV_CODEC_ID_H264 ? "h264" : "MPEG2", dec_type.profile_level, dec_attr.mem_size); vdd->config.mem_addr = (intptr_t)vdd->mem; vdd->config.mem_size = dec_attr.mem_size; vdd->config.num_spus = spu_threads; vdd->config.ppu_thread_prio = VDEC_PPU_PRIO; vdd->config.spu_thread_prio = VDEC_SPU_PRIO; vdd->config.ppu_thread_stack_size = 1 << 14; vdec_closure c; c.fn = (intptr_t)OPD32(decoder_callback); c.arg = (intptr_t)vdd; r = vdec_open(&dec_type, &vdd->config, &c, &vdd->handle); if(r) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to open Cell codec. Error 0x%x"), r); Lv2Syscall1(349, (uint64_t)vdd->mem); free(vdd); return 1; } if(mcp != NULL) { vdd->level_major = mcp->level / 10; vdd->level_minor = mcp->level % 10; } if(mc->codec_id == AV_CODEC_ID_H264 && mcp != NULL && mcp->extradata_size) h264_to_annexb_init(&vdd->annexb, mcp->extradata, mcp->extradata_size); vdd->max_order = -1; hts_mutex_init(&vdd->mtx); hts_cond_init(&vdd->audone, &vdd->mtx); hts_cond_init(&vdd->seqdone, &vdd->mtx); TRACE(TRACE_DEBUG, "VDEC", "Cell accelerated codec created using %d bytes of RAM", dec_attr.mem_size); mc->opaque = vdd; mc->decode = decoder_decode; mc->flush = decoder_flush; mc->close = decoder_close; vdec_start_sequence(vdd->handle); return 0; }
caddr_t psl1ght_sbrk_r(struct _reent* r, ptrdiff_t increment) { static int one = 1; int n, m; char * ret; // initialize if(one) { one = 0; size_t allocsize = ROUND_UP(MAX_PAGES*1024*1024, PAGE_SIZE); u32 taddr = 0; for(n = 0; n < MAX_PAGES; n++) pages[n].start = pages[n].end = NULL; if (Lv2Syscall3(348, allocsize, PAGE_SIZE_FLAG, (u64)&taddr)) { r->_errno = ENOMEM; return (void*)-1; } char* addr = (char*)(u64)taddr; current_mem = pages[0].start = addr; end_mem = pages[0].end = addr + allocsize; } if(increment > 0) { // find current page for(n = 0; n < MAX_PAGES; n++) { if(current_mem >= pages[n].start && current_mem < pages[n].end) break; } // if not found or page minor... if(n == MAX_PAGES || (current_mem + increment) > pages[n].end) { // test in the next pages if(n < (MAX_PAGES-1)) { for(m = n + 1; m < MAX_PAGES; m++) { if(pages[m].start != NULL && (pages[m].start + increment) <= pages[m].end) break; } if(m < MAX_PAGES) { current_mem = pages[m].start; goto return_ok; } } size_t allocsize = ROUND_UP(increment, MAX_PAGES*1024*1024); u32 taddr = 0; if (Lv2Syscall3(348, allocsize, PAGE_SIZE_FLAG, (u64)&taddr)) { r->_errno = ENOMEM; return (void*)-1; } char* addr = (char*)(u64)taddr; // error if addr < end_mem if(end_mem > addr) { r->_errno = ENOMEM; return (void*)-1; } end_mem = addr + allocsize; // test for increase the page if(n != MAX_PAGES && pages[n].end == addr) { pages[n].end += allocsize; } else { // test empty page for(n = 0; n < MAX_PAGES; n++) if(pages[n].start == NULL) break; if(n == MAX_PAGES) { r->_errno = ENOMEM; return (void*)-1; } pages[n].start = addr; pages[n].end = addr + allocsize; current_mem = pages[n].start; } } } else if(increment < 0){ buclea: // find current page for(n = 0; n < MAX_PAGES; n++) { if(current_mem >= pages[n].start && current_mem < pages[n].end) break; } if(n != MAX_PAGES) { if(pages[n].start > (current_mem + increment)) { if(pages[n].start == current_mem) { n--; if(n >= 0) { int incre = (int) (pages[n].end - pages[n].start); // skip pages if increment is very big if(incre < -increment) {increment += incre; current_mem = pages[n].start; goto buclea;} if(pages[n].start >= pages[n].end + increment) {ret= current_mem; current_mem = pages[n].end + increment; return ret;} } } } else goto return_ok; } r->_errno = ENOMEM; return (void*)-1; } return_ok: ret = current_mem; current_mem += increment; return ret; }
static int video_ps3_vdec_codec_create(media_codec_t *mc, const media_codec_params_t *mcp, media_pipe_t *mp) { vdec_decoder_t *vdd; struct vdec_type dec_type = {0}; struct vdec_attr dec_attr = {0}; int spu_threads; int r; switch(mc->codec_id) { case CODEC_ID_MPEG2VIDEO: if(!vdec_mpeg2_loaded) return no_lib(mp, "MPEG-2"); dec_type.codec_type = VDEC_CODEC_TYPE_MPEG2; dec_type.profile_level = VDEC_MPEG2_MP_HL; spu_threads = 1; break; case CODEC_ID_H264: if(mcp != NULL && mcp->profile == FF_PROFILE_H264_CONSTRAINED_BASELINE) return 1; // can't play this if(!vdec_h264_loaded) return no_lib(mp, "h264"); dec_type.codec_type = VDEC_CODEC_TYPE_H264; if(mcp != NULL && mcp->level > 42) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Cell-h264: Forcing level 4.2 for content in level %d.%d. This may break video playback."), mcp->level / 10, mcp->level % 10); } dec_type.profile_level = 42; spu_threads = 4; break; default: return 1; } r = vdec_query_attr(&dec_type, &dec_attr); if(r) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to query Cell codec. Error 0x%x"), r); return 1; } vdd = calloc(1, sizeof(vdec_decoder_t)); #define ROUND_UP(p, round) ((p + round - 1) & ~(round - 1)) size_t allocsize = ROUND_UP(dec_attr.mem_size, 1024*1024); u32 taddr; if(Lv2Syscall3(348, allocsize, 0x400, (u64)&taddr)) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to open Cell codec. Unable to allocate %d bytes of RAM"), dec_attr.mem_size); return 1; } vdd->mem = (void *)(uint64_t)taddr; TRACE(TRACE_DEBUG, "VDEC", "Opening codec %s level %d using %d bytes of RAM", mc->codec_id == CODEC_ID_H264 ? "h264" : "MPEG2", dec_type.profile_level, dec_attr.mem_size); vdd->config.mem_addr = (intptr_t)vdd->mem; vdd->config.mem_size = dec_attr.mem_size; vdd->config.num_spus = spu_threads; vdd->config.ppu_thread_prio = VDEC_PPU_PRIO; vdd->config.spu_thread_prio = VDEC_SPU_PRIO; vdd->config.ppu_thread_stack_size = 1 << 14; vdec_closure c; c.fn = (intptr_t)OPD32(decoder_callback); c.arg = (intptr_t)vdd; r = vdec_open(&dec_type, &vdd->config, &c, &vdd->handle); if(r) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to open Cell codec. Error 0x%x"), r); Lv2Syscall1(349, (uint64_t)vdd->mem); free(vdd); return 1; } if(mcp != NULL) { vdd->level_major = mcp->level / 10; vdd->level_minor = mcp->level % 10; } if(mc->codec_id == CODEC_ID_H264 && mcp != NULL && mcp->extradata_size) h264_to_annexb_init(&vdd->annexb, mcp->extradata, mcp->extradata_size); vdd->max_order = -1; hts_mutex_init(&vdd->mtx); hts_cond_init(&vdd->audone, &vdd->mtx); hts_cond_init(&vdd->seqdone, &vdd->mtx); TRACE(TRACE_DEBUG, "VDEC", "Cell accelerated codec created using %d bytes of RAM", dec_attr.mem_size); mc->opaque = vdd; mc->decode = decoder_decode; mc->flush = decoder_flush; mc->close = decoder_close; vdec_start_sequence(vdd->handle); return 0; }
static void init_screen(glw_ps3_t *gp) { // Allocate a 1Mb buffer, alligned to a 1Mb boundary to be our shared IO memory with the RSX. u32 taddr; Lv2Syscall3(348, 1024*1024, 0x400, (u64)&taddr); void *host_addr = (void *)(uint64_t)taddr; assert(host_addr != NULL); // Initilise Reality, which sets up the command buffer and shared IO memory gp->gr.gr_be.be_ctx = realityInit(0x10000, 1024*1024, host_addr); assert(gp->gr.gr_be.be_ctx != NULL); gcmConfiguration config; gcmGetConfiguration(&config); TRACE(TRACE_DEBUG, "RSX", "memory @ 0x%x size = %d\n", config.localAddress, config.localSize); hts_mutex_init(&rsx_mempool_lock); rsx_mempool = extent_create(0, config.localSize >> 4); rsx_address = (void *)(uint64_t)config.localAddress; VideoState state; videoGetState(0, 0, &state); // Get the current resolution videoGetResolution(state.displayMode.resolution, &gp->res); int num = gp->res.width; int den = gp->res.height; switch(state.displayMode.aspect) { case VIDEO_ASPECT_4_3: num = 4; den = 3; break; case VIDEO_ASPECT_16_9: num = 16; den = 9; break; } gp->scale = (float)(num * gp->res.height) / (float)(den * gp->res.width); TRACE(TRACE_DEBUG, "RSX", "Video resolution %d x %d aspect=%d, pixel wscale=%f", gp->res.width, gp->res.height, state.displayMode.aspect, gp->scale); gp->framebuffer_pitch = 4 * gp->res.width; // each pixel is 4 bytes gp->depthbuffer_pitch = 4 * gp->res.width; // And each value in the depth buffer is a 16 bit float // Configure the buffer format to xRGB VideoConfiguration vconfig; memset(&vconfig, 0, sizeof(VideoConfiguration)); vconfig.resolution = state.displayMode.resolution; vconfig.format = VIDEO_BUFFER_FORMAT_XRGB; vconfig.pitch = gp->framebuffer_pitch; videoConfigure(0, &vconfig, NULL, 0); videoGetState(0, 0, &state); const s32 buffer_size = gp->framebuffer_pitch * gp->res.height; const s32 depth_buffer_size = gp->depthbuffer_pitch * gp->res.height; TRACE(TRACE_DEBUG, "RSX", "Buffer will be %d bytes", buffer_size); gcmSetFlipMode(GCM_FLIP_VSYNC); // Wait for VSYNC to flip // Allocate two buffers for the RSX to draw to the screen (double buffering) gp->framebuffer[0] = rsx_alloc(buffer_size, 16); gp->framebuffer[1] = rsx_alloc(buffer_size, 16); TRACE(TRACE_DEBUG, "RSX", "Buffers at 0x%x 0x%x\n", gp->framebuffer[0], gp->framebuffer[1]); gp->depthbuffer = rsx_alloc(depth_buffer_size * 4, 16); // Setup the display buffers gcmSetDisplayBuffer(0, gp->framebuffer[0], gp->framebuffer_pitch, gp->res.width, gp->res.height); gcmSetDisplayBuffer(1, gp->framebuffer[1], gp->framebuffer_pitch, gp->res.width, gp->res.height); gp->gr.gr_br_read_pixels = rsx_read_pixels; gcmResetFlipStatus(); flip(gp, 1); }